class TimerUi: """View""" def __init__(self, app): self.time_label = Label(app.root, textvariable=app.time, anchor=CENTER, foreground='black', background='lightgray', font=('Helvetica', 60)) self.time_label.pack(fill=BOTH, expand=True) validate_command = (app.root.register(self.check), '%P') self.entry = Spinbox(app.root, from_=1, to=MAX_COUNT, textvariable=app.count_start, validate='all', validatecommand=validate_command) self.entry.pack(fill=X) self.entry.focus() buttons_frame = Frame(app.root) buttons_frame.pack(fill=X) self.start_button = Button(buttons_frame, text='Start', command=app.start_timer) self.stop_button = Button(buttons_frame, text='Stop', state=DISABLED, command=app.stop_timer) self.start_button.pack(side=LEFT, fill=X, expand=True) self.stop_button.pack(side=RIGHT, fill=X, expand=True) def check(self, new_val): return new_val.isdigit() and 1 <= int(new_val) <= MAX_COUNT def state_started(self): self.stop_button.config(state=NORMAL) self.start_button.config(state=DISABLED) self.entry.config(state=DISABLED) self.time_label.config(foreground='white', background='red') def state_stopped(self): self.stop_button.config(state=DISABLED) self.start_button.config(state=NORMAL) self.entry.config(state=NORMAL) self.time_label.config(foreground='black', background='lightgray')
class View(Frame): def __init__(self, master, controller, label, width, minimum, maximum, current, *args, **kwargs): super(View, self).__init__(master, *args, **kwargs) self._controller = controller self._create_label(label, width) self._create_spinbox(minimum, maximum) self._create_scale(minimum, maximum) def w_label(self): return self._label def w_spinbox(self): return self._spinbox def w_scale(self): return self._scale def _create_label(self, label, width): self._label = LabelTtk(self, text=label) if width: self._label.config(width=width) self._label.pack(side='left', anchor='s') def _create_spinbox(self, minimum, maximum): self._spinbox = Spinbox(self, from_=minimum, to=maximum) self._spinbox['command'] = lambda: \ self._controller.set_current(int(self._spinbox.get())) self._spinbox.bind('<Return>', lambda e: \ self._controller.set_current(self._spinbox.get())) self._spinbox.pack(side="left", anchor="s") def _create_scale(self, minimum, maximum): self._scale = Scale(self, orient="horizontal", from_=minimum, to=maximum) self._scale['command'] = lambda e: \ self._controller.set_current(self._scale.get()) self._scale.pack(side="left", fill="x", expand=True, anchor="s")
def __init__(self, form_type): Curso.__init__(self) Form.__init__(self) self.id_curso = None self.form_type = form_type fieldsFrame = Frame(self.root, padding=10) fieldsFrame.grid(row=0, column=0, padx=10, pady=10) lbl_alumnos = Label(fieldsFrame, width=30) lbl_alumnos.grid(row=2, column=0, columnspan=30) self.listaPersonas = Listbox(fieldsFrame, highlightthickness=0, selectmode="extended", height=25, width=40) self.listaPersonas.grid(row=3, column=0, columnspan=40, pady=(5,10)) btn_aceptar = Button(fieldsFrame, text="Aceptar", width=16) btn_aceptar.grid(row=4, column=0, columnspan=16) btn_cancelar = Button(fieldsFrame, text="Cancelar", width=16, command=self.hide) btn_cancelar.grid(row=4, column=26, columnspan=16) if form_type == "add": self.set_title("Inscribir alumnos") lbl_alumnos.config(text="Seleccione los alumnos:") lbl_date = Label(fieldsFrame, text="Seleccione la fecha:", width=20) lbl_date.grid(row=0, column=0, columnspan=20) self.date = StringVar() e_date = Entry(fieldsFrame, textvariable=self.date, width=30) e_date.grid(row=1, column=0, columnspan=30, pady=(0,10)) e_date.config(state="readonly") btn_date = Button(fieldsFrame, text="...", width=8, command=lambda: self.date.set(DatePicker(fieldsFrame).selection())) btn_date.grid(row=1, column=32, columnspan=8, pady=(0,10)) btn_aceptar.config(command=lambda: self.add_cursante()) elif form_type == "remove": self.set_title("Remover inscriptos") lbl_alumnos.config(text="Seleccione los inscriptos:") btn_aceptar.config(command=lambda: self.remove_cursante())
def init_ui(self): self.master.title("Speech Demo") self.pack(fill=BOTH, expand=True) label_frame = LabelFrame(self, text="System words") label_frame.pack(fill=X, padx=40, pady=20) self.labels = [] rows = 8 cols = 2 for j in range(rows): for i in range(cols): k = i + j * cols label = Label(label_frame, text=labels[k]) label.config(font=("Cambria Math", 20)) label.grid(row=j, column=i, padx=20, pady=10) self.labels += [label] self.selected = None self.after(100, self.ontick)
def init_ui(self, rows=4, cols=3): """ setup the GUI for the app """ self.master.title("Speech Demo") self.pack(fill=BOTH, expand=True) label_frame = LabelFrame(self, text="Try these categories") label_frame.pack(fill=X, padx=10, pady=10) self.labels = [] for j in range(rows): for i in range(cols): k = i + j * cols label = Label(label_frame, text=self.skeet[k]) label.config(font=("Courier", 36)) label.grid(row=j, column=i, padx=10, pady=10) self.labels += [label] self.selected = None self.after(100, self.on_tick)
class DetectionPathFrame(Frame): def __init__(self, parent, configuration): Frame.__init__(self, parent) self.configuration = configuration self.detection_path = None self.detection_path_res = configuration.detection_path self.results_path = None self.results_path_res = configuration.results_path self.init_ui() def init_ui(self): self.detection_path = Label(self, text=FileUtils.get_filename_from_path( self.configuration.detection_path)) self.detection_path.grid(row=0, column=1) Button(self, text="Input image", command=self.browse_image_path) \ .grid(row=0, column=0) self.results_path = Label(self, text=FileUtils.get_filename_from_path( self.configuration.results_path)) self.results_path.grid(row=1, column=1) Button(self, text="Result path", command=self.browse_results_path) \ .grid(row=1, column=0) def browse_image_path(self): self.detection_path_res = filedialog.askopenfilename() self.detection_path.config( text=FileUtils.get_filename_from_path(self.detection_path_res)) def browse_results_path(self): self.results_path_res = filedialog.askdirectory() self.results_path.config( text=FileUtils.get_filename_from_path(self.results_path_res)) def get_values(self): return self.detection_path_res, self.results_path_res
class ConfidenceScale(Frame): def __init__(self, master, **kw): super().__init__(master) # self.grid_propagate(0) # self.columnconfigure(0, weight=1) # self.rowconfigure(0, weight=1) self.var = kw.get('variable', IntVar()) kw['variable'] = self.var kw['from_'] = ConfidenceLevel.Low.value kw['to'] = ConfidenceLevel.VeryHigh.value # kw['command'] = self.scale_change kw['orient'] = HORIZONTAL self.lbl_scale = Label(self) self.scale = Scale(self, **kw) self.scale_font = tkfont.nametofont(Style().lookup('TLabel', 'font')).copy() self.scale_font.config(weight=tkfont.BOLD, size=9) self.lbl_scale.config(font=self.scale_font, width=3, anchor=CENTER) self.var.trace_variable('w', lambda a, b, c: self.scale_change()) self.scale.grid(row=0, column=0, sticky='ns') self.lbl_scale.grid(row=0, column=1, sticky='ns', padx=(3, 0)) def scale_change(self): rval = self.get() if rval >= ConfidenceLevel.High: fg = '#4CAF50' elif rval >= ConfidenceLevel.Medium: fg = '#FF9800' else: fg = '#FF5722' self.lbl_scale.config(foreground=fg, text=str(rval)) def get(self): return round(float(self.var.get()))
class FeedbackFrame(Frame): def __init__(self, parent): Frame.__init__(self, parent) self.output_text = None self.progress_bar = None self.progress_label = None self.init_view() def init_view(self): self.output_text = Text(self, height=10, width=40) self.output_text.grid(row=0, column=0, padx=5, pady=5, sticky="ew") self.progress_bar = Progressbar(self, orient='horizontal') self.progress_bar['maximum'] = 100 self.progress_bar.grid(row=1, column=0, padx=5, pady=5, sticky="ew") self.progress_label = Label(self) self.progress_label.grid(row=2, column=0, padx=5, pady=5, sticky="ew") def reset(self): self.progress_bar["value"] = 0 self.progress_label.config(text="") self.output_text.delete("1.0", END)
def __init__(self, **kwargs): """ Build the main screen as a notebook. """ # initialize the parent class super(ExplorerProGui, self).__init__( back_plane_ip_address=kwargs['back_plane_ip_address'], subscriber_port=kwargs['subscriber_port'], publisher_port=kwargs['publisher_port'], process_name=kwargs['process_name']) self.set_subscriber_topic('report_from_hardware') self.main = Tk() self.main.title('Demo Station For Explorer-Pro HAT') # gives weight to the cells in the grid rows = 0 while rows < 50: self.main.rowconfigure(rows, weight=1) self.main.columnconfigure(rows, weight=1) rows += 1 # Defines and places the notebook widget self.nb = Notebook(self.main, padding=20, height=300, width=800) self.nb.grid(row=1, column=0, columnspan=50, rowspan=49, sticky='NESW') # create the analog inputs tab self.analog_inputs_tab = Frame(self.nb, padding=[130, 20]) self.nb.add(self.analog_inputs_tab, text='Analog Inputs') # create an instance of the AnalogInputs class self.analog_inputs = AnalogInputs(self.analog_inputs_tab, self) # create the digital inputs tab self.digital_inputs_tab = Frame(self.nb, padding=[130, 20]) self.nb.add(self.digital_inputs_tab, text='Digital Inputs') # create an instance of the DigitalInputs class # to populate and control Signal inputs self.digital_inputs = DigitalInputs(self.digital_inputs_tab, self) # create the touch tab self.touch_tab = Frame(self.nb, padding=10) self.nb.add(self.touch_tab, text='Touch Inputs') self.touch_inputs = TouchInputs(self.touch_tab, self) # create the digital outputs tab self.digital_outputs_tab = Frame(self.nb, padding=10) self.nb.add(self.digital_outputs_tab, text='Digital Outputs') # create an instance of the DigitalOutputs class # to populate and control digital outputs self.digital_outputs = DigitalOutputs(self.digital_outputs_tab, self) # create the LED digital outputs tab self.led_digital_outputs_tab = Frame(self.nb, padding=10) self.nb.add(self.led_digital_outputs_tab, text='LED Digital Outputs') # create an instance of the DigitalOutputs class # to populate and control digital outputs self.led_digital_outputs = LedDigitalOutputs(self.led_digital_outputs_tab, self) # create the pwm output tab self.pwm_output_tab = Frame(self.nb, padding=10) self.nb.add(self.pwm_output_tab, text='PWM Outputs') self.pwm_output = PwmOutputs(self.pwm_output_tab, self) # create the LED PWM output tab self.led_pwm_output_tab = Frame(self.nb, padding=10) self.nb.add(self.led_pwm_output_tab, text='LED PWM Outputs') self.led_pwm_output = LedPwmOutputs(self.led_pwm_output_tab, self) # create the dc motors tab self.motors_tab = Frame(self.nb, padding=10) self.nb.add(self.motors_tab, text='DC Motors') self.dc_motors = DcMotors(self.motors_tab, self) l = Label(self.main, text='Copyright (c) 2019 Alan Yorinks All Rights Reserved.') l.config(font="Helvetica 8 ") l.grid(row=48, column=0, padx=[505, 0]) self.main.after(5, self.get_message) try: self.main.mainloop() except KeyboardInterrupt: self.on_closing()
class DialogPluginManager(Toplevel): def __init__(self, mainWin, modulesWithNewerFileDates): super(DialogPluginManager, self).__init__(mainWin.parent) self.ENABLE = _("Enable") self.DISABLE = _("Disable") self.parent = mainWin.parent self.cntlr = mainWin # copy plugins for temporary display self.pluginConfig = PluginManager.pluginConfig self.pluginConfigChanged = False self.uiClassMethodsChanged = False self.modulesWithNewerFileDates = modulesWithNewerFileDates parentGeometry = re.match("(\d+)x(\d+)[+]?([-]?\d+)[+]?([-]?\d+)", self.parent.geometry()) dialogX = int(parentGeometry.group(3)) dialogY = int(parentGeometry.group(4)) self.title(_("Plug-in Manager")) frame = Frame(self) # left button frame buttonFrame = Frame(frame, width=40) buttonFrame.columnconfigure(0, weight=1) addLabel = Label(buttonFrame, text=_("Find plug-in modules:"), wraplength=60, justify="center") addLocalButton = Button(buttonFrame, text=_("Locally"), command=self.findLocally) ToolTip(addLocalButton, text=_("File chooser allows selecting python module files to add (or reload) plug-ins, from the local file system."), wraplength=240) addWebButton = Button(buttonFrame, text=_("On Web"), command=self.findOnWeb) ToolTip(addWebButton, text=_("Dialog to enter URL full path to load (or reload) plug-ins, from the web or local file system."), wraplength=240) addLabel.grid(row=0, column=0, pady=4) addLocalButton.grid(row=1, column=0, pady=4) addWebButton.grid(row=2, column=0, pady=4) buttonFrame.grid(row=0, column=0, rowspan=2, sticky=(N, S, W), padx=3, pady=3) # right tree frame (plugins already known to arelle) modulesFrame = Frame(frame, width=700) vScrollbar = Scrollbar(modulesFrame, orient=VERTICAL) hScrollbar = Scrollbar(modulesFrame, orient=HORIZONTAL) self.modulesView = Treeview(modulesFrame, xscrollcommand=hScrollbar.set, yscrollcommand=vScrollbar.set, height=7) self.modulesView.grid(row=0, column=0, sticky=(N, S, E, W)) self.modulesView.bind('<<TreeviewSelect>>', self.moduleSelect) hScrollbar["command"] = self.modulesView.xview hScrollbar.grid(row=1, column=0, sticky=(E,W)) vScrollbar["command"] = self.modulesView.yview vScrollbar.grid(row=0, column=1, sticky=(N,S)) modulesFrame.columnconfigure(0, weight=1) modulesFrame.rowconfigure(0, weight=1) modulesFrame.grid(row=0, column=1, columnspan=4, sticky=(N, S, E, W), padx=3, pady=3) self.modulesView.focus_set() self.modulesView.column("#0", width=120, anchor="w") self.modulesView.heading("#0", text=_("Name")) self.modulesView["columns"] = ("author", "ver", "status", "date", "update", "descr", "license") self.modulesView.column("author", width=100, anchor="w", stretch=False) self.modulesView.heading("author", text=_("Author")) self.modulesView.column("ver", width=50, anchor="w", stretch=False) self.modulesView.heading("ver", text=_("Version")) self.modulesView.column("status", width=50, anchor="w", stretch=False) self.modulesView.heading("status", text=_("Status")) self.modulesView.column("date", width=70, anchor="w", stretch=False) self.modulesView.heading("date", text=_("File Date")) self.modulesView.column("update", width=50, anchor="w", stretch=False) self.modulesView.heading("update", text=_("Update")) self.modulesView.column("descr", width=200, anchor="w", stretch=False) self.modulesView.heading("descr", text=_("Description")) self.modulesView.column("license", width=70, anchor="w", stretch=False) self.modulesView.heading("license", text=_("License")) classesFrame = Frame(frame) vScrollbar = Scrollbar(classesFrame, orient=VERTICAL) hScrollbar = Scrollbar(classesFrame, orient=HORIZONTAL) self.classesView = Treeview(classesFrame, xscrollcommand=hScrollbar.set, yscrollcommand=vScrollbar.set, height=5) self.classesView.grid(row=0, column=0, sticky=(N, S, E, W)) hScrollbar["command"] = self.classesView.xview hScrollbar.grid(row=1, column=0, sticky=(E,W)) vScrollbar["command"] = self.classesView.yview vScrollbar.grid(row=0, column=1, sticky=(N,S)) classesFrame.columnconfigure(0, weight=1) classesFrame.rowconfigure(0, weight=1) classesFrame.grid(row=1, column=1, columnspan=4, sticky=(N, S, E, W), padx=3, pady=3) self.classesView.focus_set() self.classesView.column("#0", width=200, anchor="w") self.classesView.heading("#0", text=_("Class")) self.classesView["columns"] = ("modules") self.classesView.column("modules", width=500, anchor="w", stretch=False) self.classesView.heading("modules", text=_("Modules")) # bottom frame module info details moduleInfoFrame = Frame(frame, width=700) moduleInfoFrame.columnconfigure(1, weight=1) self.moduleNameLabel = Label(moduleInfoFrame, wraplength=600, justify="left", font=font.Font(family='Helvetica', size=12, weight='bold')) self.moduleNameLabel.grid(row=0, column=0, columnspan=4, sticky=W) self.moduleAuthorHdr = Label(moduleInfoFrame, text=_("author:"), state=DISABLED) self.moduleAuthorHdr.grid(row=1, column=0, sticky=W) self.moduleAuthorLabel = Label(moduleInfoFrame, wraplength=600, justify="left") self.moduleAuthorLabel.grid(row=1, column=1, columnspan=3, sticky=W) self.moduleDescrHdr = Label(moduleInfoFrame, text=_("description:"), state=DISABLED) self.moduleDescrHdr.grid(row=2, column=0, sticky=W) self.moduleDescrLabel = Label(moduleInfoFrame, wraplength=600, justify="left") self.moduleDescrLabel.grid(row=2, column=1, columnspan=3, sticky=W) self.moduleClassesHdr = Label(moduleInfoFrame, text=_("classes:"), state=DISABLED) self.moduleClassesHdr.grid(row=3, column=0, sticky=W) self.moduleClassesLabel = Label(moduleInfoFrame, wraplength=600, justify="left") self.moduleClassesLabel.grid(row=3, column=1, columnspan=3, sticky=W) ToolTip(self.moduleClassesLabel, text=_("List of classes that this plug-in handles."), wraplength=240) self.moduleUrlHdr = Label(moduleInfoFrame, text=_("URL:"), state=DISABLED) self.moduleUrlHdr.grid(row=4, column=0, sticky=W) self.moduleUrlLabel = Label(moduleInfoFrame, wraplength=600, justify="left") self.moduleUrlLabel.grid(row=4, column=1, columnspan=3, sticky=W) ToolTip(self.moduleUrlLabel, text=_("URL of plug-in module (local file path or web loaded file)."), wraplength=240) self.moduleDateHdr = Label(moduleInfoFrame, text=_("date:"), state=DISABLED) self.moduleDateHdr.grid(row=5, column=0, sticky=W) self.moduleDateLabel = Label(moduleInfoFrame, wraplength=600, justify="left") self.moduleDateLabel.grid(row=5, column=1, columnspan=3, sticky=W) ToolTip(self.moduleDateLabel, text=_("Date of currently loaded module file (with parenthetical node when an update is available)."), wraplength=240) self.moduleLicenseHdr = Label(moduleInfoFrame, text=_("license:"), state=DISABLED) self.moduleLicenseHdr.grid(row=6, column=0, sticky=W) self.moduleLicenseLabel = Label(moduleInfoFrame, wraplength=600, justify="left") self.moduleLicenseLabel.grid(row=6, column=1, columnspan=3, sticky=W) self.moduleEnableButton = Button(moduleInfoFrame, text=self.ENABLE, state=DISABLED, command=self.moduleEnable) ToolTip(self.moduleEnableButton, text=_("Enable/disable plug in."), wraplength=240) self.moduleEnableButton.grid(row=7, column=1, sticky=E) self.moduleReloadButton = Button(moduleInfoFrame, text=_("Reload"), state=DISABLED, command=self.moduleReload) ToolTip(self.moduleReloadButton, text=_("Reload/update plug in."), wraplength=240) self.moduleReloadButton.grid(row=7, column=2, sticky=E) self.moduleRemoveButton = Button(moduleInfoFrame, text=_("Remove"), state=DISABLED, command=self.moduleRemove) ToolTip(self.moduleRemoveButton, text=_("Remove plug in from plug in table (does not erase the plug in's file)."), wraplength=240) self.moduleRemoveButton.grid(row=7, column=3, sticky=E) moduleInfoFrame.grid(row=2, column=0, columnspan=5, sticky=(N, S, E, W), padx=3, pady=3) moduleInfoFrame.config(borderwidth=4, relief="groove") okButton = Button(frame, text=_("Close"), command=self.ok) ToolTip(okButton, text=_("Accept and changes (if any) and close dialog."), wraplength=240) cancelButton = Button(frame, text=_("Cancel"), command=self.close) ToolTip(cancelButton, text=_("Cancel changes (if any) and close dialog."), wraplength=240) okButton.grid(row=3, column=3, sticky=(S,E), pady=3) cancelButton.grid(row=3, column=4, sticky=(S,E), pady=3, padx=3) self.loadTreeViews() frame.grid(row=0, column=0, sticky=(N,S,E,W)) frame.columnconfigure(0, weight=1) frame.columnconfigure(1, weight=1) window = self.winfo_toplevel() window.columnconfigure(0, weight=1) self.geometry("+{0}+{1}".format(dialogX+50,dialogY+100)) self.bind("<Return>", self.ok) self.bind("<Escape>", self.close) self.protocol("WM_DELETE_WINDOW", self.close) self.grab_set() self.wait_window(self) def loadTreeViews(self): self.selectedModule = None # clear previous treeview entries for previousNode in self.modulesView.get_children(""): self.modulesView.delete(previousNode) for i, moduleItem in enumerate(sorted(self.pluginConfig.get("modules", {}).items())): moduleInfo = moduleItem[1] name = moduleInfo.get("name", moduleItem[0]) node = self.modulesView.insert("", "end", name, text=name) self.modulesView.set(node, "author", moduleInfo.get("author")) self.modulesView.set(node, "ver", moduleInfo.get("version")) self.modulesView.set(node, "status", moduleInfo.get("status")) self.modulesView.set(node, "date", moduleInfo.get("fileDate")) if name in self.modulesWithNewerFileDates: self.modulesView.set(node, "update", _("available")) self.modulesView.set(node, "descr", moduleInfo.get("description")) self.modulesView.set(node, "license", moduleInfo.get("license")) # clear previous treeview entries for previousNode in self.classesView.get_children(""): self.classesView.delete(previousNode) for i, classItem in enumerate(sorted(self.pluginConfig.get("classes", {}).items())): className, moduleList = classItem node = self.classesView.insert("", "end", className, text=className) self.classesView.set(node, "modules", ', '.join(moduleList)) self.moduleSelect() # clear out prior selection def ok(self, event=None): if self.pluginConfigChanged: PluginManager.pluginConfig = self.pluginConfig PluginManager.pluginConfigChanged = True PluginManager.reset() # force reloading of modules if self.uiClassMethodsChanged: # may require reloading UI if messagebox.askyesno(_("User interface plug-in change"), _("A change in plug-in class methods may have affected the menus " "of the user interface. It may be necessary to restart Arelle to " "access the menu entries or the changes to their plug-in methods. \n\n" "Should Arelle restart with changed user interface language, " "(if there are any unsaved changes they would be lost!)?"), parent=self): self.cntlr.uiThreadQueue.put((self.cntlr.quit, [None, True])) self.close() def close(self, event=None): self.parent.focus_set() self.destroy() def moduleSelect(self, *args): node = (self.modulesView.selection() or (None,))[0] moduleInfo = self.pluginConfig.get("modules", {}).get(node) if moduleInfo: self.selectedModule = node name = moduleInfo["name"] self.moduleNameLabel.config(text=name) self.moduleAuthorHdr.config(state=ACTIVE) self.moduleAuthorLabel.config(text=moduleInfo["author"]) self.moduleDescrHdr.config(state=ACTIVE) self.moduleDescrLabel.config(text=moduleInfo["description"]) self.moduleClassesHdr.config(state=ACTIVE) self.moduleClassesLabel.config(text=', '.join(moduleInfo["classMethods"])) self.moduleUrlHdr.config(state=ACTIVE) self.moduleUrlLabel.config(text=moduleInfo["moduleURL"]) self.moduleDateHdr.config(state=ACTIVE) self.moduleDateLabel.config(text=moduleInfo["fileDate"] + " " + (_("(an update is available)") if name in self.modulesWithNewerFileDates else "")) self.moduleLicenseHdr.config(state=ACTIVE) self.moduleLicenseLabel.config(text=moduleInfo["license"]) self.moduleEnableButton.config(state=ACTIVE, text={"enabled":self.DISABLE, "disabled":self.ENABLE}[moduleInfo["status"]]) self.moduleReloadButton.config(state=ACTIVE) self.moduleRemoveButton.config(state=ACTIVE) else: self.selectedModule = None self.moduleNameLabel.config(text="") self.moduleAuthorHdr.config(state=DISABLED) self.moduleAuthorLabel.config(text="") self.moduleDescrHdr.config(state=DISABLED) self.moduleDescrLabel.config(text="") self.moduleClassesHdr.config(state=DISABLED) self.moduleClassesLabel.config(text="") self.moduleUrlHdr.config(state=DISABLED) self.moduleUrlLabel.config(text="") self.moduleDateHdr.config(state=DISABLED) self.moduleDateLabel.config(text="") self.moduleLicenseHdr.config(state=DISABLED) self.moduleLicenseLabel.config(text="") self.moduleEnableButton.config(state=DISABLED, text=self.ENABLE) self.moduleReloadButton.config(state=DISABLED) self.moduleRemoveButton.config(state=DISABLED) def findLocally(self): filename = self.cntlr.uiFileDialog("open", owner=self, title=_("Choose plug-in module file"), initialdir=self.cntlr.config.setdefault("pluginOpenDir","."), filetypes=[(_("Python files"), "*.py")], defaultextension=".py") if filename: self.cntlr.config["pluginOpenDir"] = os.path.dirname(filename) moduleInfo = PluginManager.moduleModuleInfo(filename) self.loadFoundModuleInfo(moduleInfo, filename) def findOnWeb(self): url = DialogURL.askURL(self) if url: # url is the in-cache or local file moduleInfo = PluginManager.moduleModuleInfo(url) self.cntlr.showStatus("") # clear web loading status self.loadFoundModuleInfo(moduleInfo, url) def loadFoundModuleInfo(self, moduleInfo, url): if moduleInfo and moduleInfo.get("name"): self.addPluginConfigModuleInfo(moduleInfo) self.loadTreeViews() else: messagebox.showwarning(_("Module is not a plug-in"), _("File does not contain a python program with an appropriate __pluginInfo__ declaration: \n\n{0}") .format(url), parent=self) def removePluginConfigModuleInfo(self, name): moduleInfo = self.pluginConfig["modules"].get(name) if moduleInfo: for classMethod in moduleInfo["classMethods"]: classMethods = self.pluginConfig["classes"].get(classMethod) if classMethods and name in classMethods: classMethods.remove(name) if not classMethods: # list has become unused del self.pluginConfig["classes"][classMethod] # remove class if classMethod.startswith("CntlrWinMain.Menu"): self.uiClassMethodsChanged = True # may require reloading UI del self.pluginConfig["modules"][name] self.pluginConfigChanged = True def addPluginConfigModuleInfo(self, moduleInfo): name = moduleInfo["name"] self.removePluginConfigModuleInfo(name) # remove any prior entry for this module self.modulesWithNewerFileDates.discard(name) # no longer has an update available self.pluginConfig["modules"][name] = moduleInfo # add classes for classMethod in moduleInfo["classMethods"]: classMethods = self.pluginConfig["classes"].setdefault(classMethod, []) if name not in classMethods: classMethods.append(name) if classMethod.startswith("CntlrWinMain.Menu"): self.uiClassMethodsChanged = True # may require reloading UI self.pluginConfigChanged = True def moduleEnable(self): if self.selectedModule in self.pluginConfig["modules"]: moduleInfo = self.pluginConfig["modules"][self.selectedModule] if self.moduleEnableButton['text'] == self.ENABLE: moduleInfo["status"] = "enabled" self.moduleEnableButton['text'] = self.DISABLE elif self.moduleEnableButton['text'] == self.DISABLE: moduleInfo["status"] = "disabled" self.moduleEnableButton['text'] = self.ENABLE self.pluginConfigChanged = True self.loadTreeViews() def moduleReload(self): if self.selectedModule in self.pluginConfig["modules"]: url = self.pluginConfig["modules"][self.selectedModule].get("moduleURL") if url: moduleInfo = PluginManager.moduleModuleInfo(url, reload=True) if moduleInfo: self.addPluginConfigModuleInfo(moduleInfo) self.loadTreeViews() self.cntlr.showStatus(_("{0} reloaded").format(moduleInfo.get("name")), clearAfter=5000) else: messagebox.showwarning(_("Module error"), _("File or module cannot be reloaded: \n\n{0}") .format(url), parent=self) def moduleRemove(self): if self.selectedModule in self.pluginConfig["modules"]: self.removePluginConfigModuleInfo(self.selectedModule) self.pluginConfigChanged = True self.loadTreeViews()
class Example(Frame): def __init__(self, parent): Frame.__init__(self, parent) self.parent = parent self.initUI() def initUI(self): self.username = '' self.r = praw.Reddit(USERAGENT) self.parent.title("") self.style = Style() self.style.theme_use("clam") self.pack(fill=BOTH, expand = 1) self.labelU = Label(self, text="U:") self.labelP = Label(self, text="P:") self.entryUsername = Entry(self) self.entryUsername.config(relief='flat') self.entryUsername.focus_set() self.entryUsername.bind('<Return>', lambda event: self.login(self.entryUsername.get())) self.entryUsername.bind('<Up>', lambda event: self.entryUsername.insert(0, self.username)) self.quitbutton = Button(self, text="Quit", command= lambda: self.quit()) self.quitbutton.config(width=6) self.labelKarma = Label(self, text = '•') self.labelKarma.grid(row = 3, column = 1) self.labelU.grid(row=0, column=0) self.entryUsername.grid(row=0, column=1) self.quitbutton.grid(row=2, column=1, pady=4) self.usernamelabel = Label(self, text='') self.usernamelabel.grid(row=1, column=1) def login(self, username): print('U: ' + username) self.username = username self.entryUsername.delete(0, 200) if username == '': self.entryUsername.focus_set() else: try: self.user = self.r.get_redditor(self.username) lkarma = str(self.user.link_karma) ckarma = str(self.user.comment_karma) lkarma = self.karmaRound(lkarma) ckarma = self.karmaRound(ckarma) karmastring = lkarma + ' • ' + ckarma self.labelKarma.config(text = karmastring) self.usernamelabel.config(text= self.username) except: self.labelKarma.config(text = '•') self.usernamelabel.config(text= 'User not found') pass def karmaRound(self, karma): if len(karma) > 4 and len(karma) < 7: tstring = karma[:-3] tstring2 = karma[-3:] karma = tstring + '.' + tstring2[:2] + 'K' return karma if len(karma) > 6: tstring = karma[:-6] tstring2 = karma[-6:] karma = tstring + '.' + tstring2[:2] + 'M' return karma else: return karma
def setupUI(self): # build UI base on URLS if self.option[2] == SEARCH: # title window label_title = Label(self, text='Search Photos') label_title.config(anchor='center', foreground='white', background='#8e44ad') label_title.grid(row=0, column=0, columnspan=6, sticky='we') # progress self.progress = Progressbar(self) self.progress.config(orient='horizontal', length=100, mode='determinate') self.progress.grid(row=2, column=0, columnspan=5, sticky='we') self.var_progress = StringVar() self.var_progress.set('0%') self.label_show_progress = Label(self) self.label_show_progress.config(textvariable=self.var_progress, anchor='center') self.label_show_progress.var = self.var_progress self.label_show_progress.grid(row=2, column=5, sticky='w') # query self.label_query = Label(self, text='Query') self.label_query.grid(row=1, column=0, sticky='e') self.var_entry_query = StringVar() self.entry_query = Entry(self) self.entry_query.config(textvariable=self.var_entry_query, state='readonly') self.entry_query.grid(row=1, column=1, sticky='w') # total self.var_total = StringVar() self.var_total.set('Total') self.label_total = Label(self, textvariable=self.var_total) self.label_total.grid(row=1, column=2, sticky='e') self.var_entry_total = IntVar() self.entry_total = Entry(self) self.entry_total.config(textvariable=self.var_entry_total, state='readonly') self.entry_total.grid(row=1, column=3, sticky='w') # total pages self.label_total_page = Label(self, text='Total pages:') self.label_total_page.grid(row=1, column=4, sticky='e') self.var_entry_total_pages = IntVar() self.entry_total_page = Entry(self) self.entry_total_page.config(textvariable=self.var_entry_total_pages, state='readonly') self.entry_total_page.grid(row=1, column=5, sticky='w') # show image is downloaded self.label_image_downloaded = Label(self, anchor='center') self.label_image_downloaded.grid(row=3, column=0, columnspan=6, sticky='wesn') # self.change_ui() elif self.option[2] == LIST: # title window label_title = Label(self, text='List of Photos') label_title.config( anchor='center', foreground='white', background='#2c3e50') label_title.grid(row=0, column=0, columnspan=4, sticky='we') # progress self.progress = Progressbar(self) self.progress.config(orient='horizontal', length=100, mode='determinate') self.progress.grid(row=2, column=0, columnspan=3, sticky='we') self.var_progress = StringVar() self.var_progress.set('0%') self.label_show_progress = Label(self) self.label_show_progress.config( textvariable=self.var_progress, anchor='center') self.label_show_progress.var = self.var_progress self.label_show_progress.grid(row=2, column=3, sticky='w') # query self.label_query = Label(self, text='Query:') self.label_query.grid(row=1, column=0, sticky='e') self.entry_query = Entry(self) self.entry_query.insert(0,'LIST') self.entry_query.config(state='readonly') self.entry_query.grid(row=1, column=1, sticky='w') # amount self.label_total = Label(self, text='Amount:') self.label_total.grid(row=1, column=2, sticky='e') self.entry_total = Entry(self) self.entry_total.insert(0,self.option[3]['per_page']) self.entry_total.config(state='readonly') self.entry_total.grid(row=1, column=3, sticky='w') # show image is downloaded self.label_image_downloaded = Label(self, anchor='center') self.label_image_downloaded.grid( row=3, column=0, columnspan=4, sticky='wesn') # self.change_ui() elif self.option[2] == RANDOM: # title window label_title = Label(self, text='Random Photos') label_title.config( anchor='center', foreground='white', background='#16a085') label_title.grid(row=0, column=0, columnspan=4, sticky='we') # progress self.progress = Progressbar(self) self.progress.config(orient='horizontal', length=100, mode='determinate') self.progress.grid(row=2, column=0, columnspan=3, sticky='we') self.var_progress = StringVar() self.var_progress.set('0%') self.label_show_progress = Label(self) self.label_show_progress.config( textvariable=self.var_progress, anchor='center') self.label_show_progress.var = self.var_progress self.label_show_progress.grid(row=2, column=3, sticky='w') # query self.label_query = Label(self, text='Query') self.label_query.grid(row=1, column=0, sticky='e') self.entry_query = Entry(self) self.entry_query.insert(0,'RANDOM') self.entry_query.config(state='readonly') self.entry_query.grid(row=1, column=1, sticky='w') # amount self.label_total = Label(self, text='Amount') self.label_total.grid(row=1, column=2, sticky='e') self.var_entry_total = IntVar() if self.option[3]['count'] > 30: self.var_entry_total.set(30) else: self.var_entry_total.set(self.option[3]['count']) self.entry_total = Entry(self) self.entry_total.config(textvariable=self.var_entry_total, state='readonly') self.entry_total.grid(row=1, column=3, sticky='w') # show image is downloaded self.label_image_downloaded = Label(self, anchor='center') self.label_image_downloaded.grid( row=3, column=0, columnspan=4, sticky='wesn')
class DialogPluginManager(Toplevel): def __init__(self, mainWin, modulesWithNewerFileDates): super(DialogPluginManager, self).__init__(mainWin.parent) self.ENABLE = _("Enable") self.DISABLE = _("Disable") self.parent = mainWin.parent self.cntlr = mainWin # copy plugins for temporary display self.pluginConfig = PluginManager.pluginConfig self.pluginConfigChanged = False self.uiClassMethodsChanged = False self.modelClassesChanged = False self.disclosureSystemTypesChanged = False self.modulesWithNewerFileDates = modulesWithNewerFileDates parentGeometry = re.match("(\d+)x(\d+)[+]?([-]?\d+)[+]?([-]?\d+)", self.parent.geometry()) dialogX = int(parentGeometry.group(3)) dialogY = int(parentGeometry.group(4)) self.title(_("Plug-in Manager")) frame = Frame(self) # left button frame buttonFrame = Frame(frame, width=40) buttonFrame.columnconfigure(0, weight=1) addLabel = Label(buttonFrame, text=_("Find plug-in modules:"), wraplength=60, justify="center") addLocalButton = Button(buttonFrame, text=_("Locally"), command=self.findLocally) ToolTip(addLocalButton, text=_("File chooser allows selecting python module files to add (or reload) plug-ins, from the local file system."), wraplength=240) addWebButton = Button(buttonFrame, text=_("On Web"), command=self.findOnWeb) ToolTip(addWebButton, text=_("Dialog to enter URL full path to load (or reload) plug-ins, from the web or local file system."), wraplength=240) addLabel.grid(row=0, column=0, pady=4) addLocalButton.grid(row=1, column=0, pady=4) addWebButton.grid(row=2, column=0, pady=4) buttonFrame.grid(row=0, column=0, rowspan=2, sticky=(N, S, W), padx=3, pady=3) # right tree frame (plugins already known to arelle) modulesFrame = Frame(frame, width=700) vScrollbar = Scrollbar(modulesFrame, orient=VERTICAL) hScrollbar = Scrollbar(modulesFrame, orient=HORIZONTAL) self.modulesView = Treeview(modulesFrame, xscrollcommand=hScrollbar.set, yscrollcommand=vScrollbar.set, height=7) self.modulesView.grid(row=0, column=0, sticky=(N, S, E, W)) self.modulesView.bind('<<TreeviewSelect>>', self.moduleSelect) hScrollbar["command"] = self.modulesView.xview hScrollbar.grid(row=1, column=0, sticky=(E,W)) vScrollbar["command"] = self.modulesView.yview vScrollbar.grid(row=0, column=1, sticky=(N,S)) modulesFrame.columnconfigure(0, weight=1) modulesFrame.rowconfigure(0, weight=1) modulesFrame.grid(row=0, column=1, columnspan=4, sticky=(N, S, E, W), padx=3, pady=3) self.modulesView.focus_set() self.modulesView.column("#0", width=120, anchor="w") self.modulesView.heading("#0", text=_("Name")) self.modulesView["columns"] = ("author", "ver", "status", "date", "update", "descr", "license") self.modulesView.column("author", width=100, anchor="w", stretch=False) self.modulesView.heading("author", text=_("Author")) self.modulesView.column("ver", width=50, anchor="w", stretch=False) self.modulesView.heading("ver", text=_("Version")) self.modulesView.column("status", width=50, anchor="w", stretch=False) self.modulesView.heading("status", text=_("Status")) self.modulesView.column("date", width=70, anchor="w", stretch=False) self.modulesView.heading("date", text=_("File Date")) self.modulesView.column("update", width=50, anchor="w", stretch=False) self.modulesView.heading("update", text=_("Update")) self.modulesView.column("descr", width=200, anchor="w", stretch=False) self.modulesView.heading("descr", text=_("Description")) self.modulesView.column("license", width=70, anchor="w", stretch=False) self.modulesView.heading("license", text=_("License")) classesFrame = Frame(frame) vScrollbar = Scrollbar(classesFrame, orient=VERTICAL) hScrollbar = Scrollbar(classesFrame, orient=HORIZONTAL) self.classesView = Treeview(classesFrame, xscrollcommand=hScrollbar.set, yscrollcommand=vScrollbar.set, height=5) self.classesView.grid(row=0, column=0, sticky=(N, S, E, W)) hScrollbar["command"] = self.classesView.xview hScrollbar.grid(row=1, column=0, sticky=(E,W)) vScrollbar["command"] = self.classesView.yview vScrollbar.grid(row=0, column=1, sticky=(N,S)) classesFrame.columnconfigure(0, weight=1) classesFrame.rowconfigure(0, weight=1) classesFrame.grid(row=1, column=1, columnspan=4, sticky=(N, S, E, W), padx=3, pady=3) self.classesView.focus_set() self.classesView.column("#0", width=200, anchor="w") self.classesView.heading("#0", text=_("Class")) self.classesView["columns"] = ("modules",) self.classesView.column("modules", width=500, anchor="w", stretch=False) self.classesView.heading("modules", text=_("Modules")) # bottom frame module info details moduleInfoFrame = Frame(frame, width=700) moduleInfoFrame.columnconfigure(1, weight=1) self.moduleNameLabel = Label(moduleInfoFrame, wraplength=600, justify="left", font=font.Font(family='Helvetica', size=12, weight='bold')) self.moduleNameLabel.grid(row=0, column=0, columnspan=4, sticky=W) self.moduleAuthorHdr = Label(moduleInfoFrame, text=_("author:"), state=DISABLED) self.moduleAuthorHdr.grid(row=1, column=0, sticky=W) self.moduleAuthorLabel = Label(moduleInfoFrame, wraplength=600, justify="left") self.moduleAuthorLabel.grid(row=1, column=1, columnspan=3, sticky=W) self.moduleDescrHdr = Label(moduleInfoFrame, text=_("description:"), state=DISABLED) self.moduleDescrHdr.grid(row=2, column=0, sticky=W) self.moduleDescrLabel = Label(moduleInfoFrame, wraplength=600, justify="left") self.moduleDescrLabel.grid(row=2, column=1, columnspan=3, sticky=W) self.moduleClassesHdr = Label(moduleInfoFrame, text=_("classes:"), state=DISABLED) self.moduleClassesHdr.grid(row=3, column=0, sticky=W) self.moduleClassesLabel = Label(moduleInfoFrame, wraplength=600, justify="left") self.moduleClassesLabel.grid(row=3, column=1, columnspan=3, sticky=W) ToolTip(self.moduleClassesLabel, text=_("List of classes that this plug-in handles."), wraplength=240) self.moduleUrlHdr = Label(moduleInfoFrame, text=_("URL:"), state=DISABLED) self.moduleUrlHdr.grid(row=4, column=0, sticky=W) self.moduleUrlLabel = Label(moduleInfoFrame, wraplength=600, justify="left") self.moduleUrlLabel.grid(row=4, column=1, columnspan=3, sticky=W) ToolTip(self.moduleUrlLabel, text=_("URL of plug-in module (local file path or web loaded file)."), wraplength=240) self.moduleDateHdr = Label(moduleInfoFrame, text=_("date:"), state=DISABLED) self.moduleDateHdr.grid(row=5, column=0, sticky=W) self.moduleDateLabel = Label(moduleInfoFrame, wraplength=600, justify="left") self.moduleDateLabel.grid(row=5, column=1, columnspan=3, sticky=W) ToolTip(self.moduleDateLabel, text=_("Date of currently loaded module file (with parenthetical node when an update is available)."), wraplength=240) self.moduleLicenseHdr = Label(moduleInfoFrame, text=_("license:"), state=DISABLED) self.moduleLicenseHdr.grid(row=6, column=0, sticky=W) self.moduleLicenseLabel = Label(moduleInfoFrame, wraplength=600, justify="left") self.moduleLicenseLabel.grid(row=6, column=1, columnspan=3, sticky=W) self.moduleEnableButton = Button(moduleInfoFrame, text=self.ENABLE, state=DISABLED, command=self.moduleEnable) ToolTip(self.moduleEnableButton, text=_("Enable/disable plug in."), wraplength=240) self.moduleEnableButton.grid(row=7, column=1, sticky=E) self.moduleReloadButton = Button(moduleInfoFrame, text=_("Reload"), state=DISABLED, command=self.moduleReload) ToolTip(self.moduleReloadButton, text=_("Reload/update plug in."), wraplength=240) self.moduleReloadButton.grid(row=7, column=2, sticky=E) self.moduleRemoveButton = Button(moduleInfoFrame, text=_("Remove"), state=DISABLED, command=self.moduleRemove) ToolTip(self.moduleRemoveButton, text=_("Remove plug in from plug in table (does not erase the plug in's file)."), wraplength=240) self.moduleRemoveButton.grid(row=7, column=3, sticky=E) moduleInfoFrame.grid(row=2, column=0, columnspan=5, sticky=(N, S, E, W), padx=3, pady=3) moduleInfoFrame.config(borderwidth=4, relief="groove") okButton = Button(frame, text=_("Close"), command=self.ok) ToolTip(okButton, text=_("Accept and changes (if any) and close dialog."), wraplength=240) cancelButton = Button(frame, text=_("Cancel"), command=self.close) ToolTip(cancelButton, text=_("Cancel changes (if any) and close dialog."), wraplength=240) okButton.grid(row=3, column=3, sticky=(S,E), pady=3) cancelButton.grid(row=3, column=4, sticky=(S,E), pady=3, padx=3) enableDisableFrame = Frame(frame) enableDisableFrame.grid(row=3, column=1, sticky=(S,W), pady=3) enableAllButton = Button(enableDisableFrame, text=_("Enable All"), command=self.enableAll) ToolTip(enableAllButton, text=_("Enable all plug ins."), wraplength=240) disableAllButton = Button(enableDisableFrame, text=_("Disable All"), command=self.disableAll) ToolTip(disableAllButton, text=_("Disable all plug ins."), wraplength=240) enableAllButton.grid(row=1, column=1) disableAllButton.grid(row=1, column=2) self.loadTreeViews() self.geometry("+{0}+{1}".format(dialogX+50,dialogY+100)) frame.grid(row=0, column=0, sticky=(N,S,E,W)) frame.columnconfigure(0, weight=0) frame.columnconfigure(1, weight=1) frame.rowconfigure(0, weight=1) window = self.winfo_toplevel() window.columnconfigure(0, weight=1) window.rowconfigure(0, weight=1) self.bind("<Return>", self.ok) self.bind("<Escape>", self.close) self.protocol("WM_DELETE_WINDOW", self.close) self.grab_set() self.wait_window(self) def loadTreeViews(self): self.selectedModule = None # clear previous treeview entries for previousNode in self.modulesView.get_children(""): self.modulesView.delete(previousNode) for i, moduleItem in enumerate(sorted(self.pluginConfig.get("modules", {}).items())): moduleInfo = moduleItem[1] name = moduleInfo.get("name", moduleItem[0]) node = self.modulesView.insert("", "end", name, text=name) self.modulesView.set(node, "author", moduleInfo.get("author")) self.modulesView.set(node, "ver", moduleInfo.get("version")) self.modulesView.set(node, "status", moduleInfo.get("status")) self.modulesView.set(node, "date", moduleInfo.get("fileDate")) if name in self.modulesWithNewerFileDates: self.modulesView.set(node, "update", _("available")) self.modulesView.set(node, "descr", moduleInfo.get("description")) self.modulesView.set(node, "license", moduleInfo.get("license")) # clear previous treeview entries for previousNode in self.classesView.get_children(""): self.classesView.delete(previousNode) for i, classItem in enumerate(sorted(self.pluginConfig.get("classes", {}).items())): className, moduleList = classItem node = self.classesView.insert("", "end", className, text=className) self.classesView.set(node, "modules", ', '.join(moduleList)) self.moduleSelect() # clear out prior selection def ok(self, event=None): if self.pluginConfigChanged: PluginManager.pluginConfig = self.pluginConfig PluginManager.pluginConfigChanged = True PluginManager.reset() # force reloading of modules if self.uiClassMethodsChanged or self.modelClassesChanged or self.disclosureSystemTypesChanged: # may require reloading UI affectedItems = "" if self.uiClassMethodsChanged: affectedItems += _("menus of the user interface") if self.modelClassesChanged: if self.uiClassMethodsChanged: affectedItems += _(" and ") affectedItems += _("model objects of the processor") if (self.uiClassMethodsChanged or self.modelClassesChanged): affectedItems += _(" and ") if self.disclosureSystemTypesChanged: if (self.uiClassMethodsChanged or self.modelClassesChanged): affectedItems += _(" and ") affectedItems += _("disclosure system types") if messagebox.askyesno(_("User interface plug-in change"), _("A change in plug-in class methods may have affected {0}. " "Please restart Arelle to due to these changes. \n\n" "Should Arelle restart itself now " "(if there are any unsaved changes they would be lost!)?" ).format(affectedItems), parent=self): self.cntlr.uiThreadQueue.put((self.cntlr.quit, [None, True])) self.close() def close(self, event=None): self.parent.focus_set() self.destroy() def moduleSelect(self, *args): node = (self.modulesView.selection() or (None,))[0] moduleInfo = self.pluginConfig.get("modules", {}).get(node) if moduleInfo: self.selectedModule = node name = moduleInfo["name"] self.moduleNameLabel.config(text=name) self.moduleAuthorHdr.config(state=ACTIVE) self.moduleAuthorLabel.config(text=moduleInfo["author"]) self.moduleDescrHdr.config(state=ACTIVE) self.moduleDescrLabel.config(text=moduleInfo["description"]) self.moduleClassesHdr.config(state=ACTIVE) self.moduleClassesLabel.config(text=', '.join(moduleInfo["classMethods"])) self.moduleUrlHdr.config(state=ACTIVE) self.moduleUrlLabel.config(text=moduleInfo["moduleURL"]) self.moduleDateHdr.config(state=ACTIVE) self.moduleDateLabel.config(text=moduleInfo["fileDate"] + " " + (_("(an update is available)") if name in self.modulesWithNewerFileDates else "")) self.moduleLicenseHdr.config(state=ACTIVE) self.moduleLicenseLabel.config(text=moduleInfo["license"]) self.moduleEnableButton.config(state=ACTIVE, text={"enabled":self.DISABLE, "disabled":self.ENABLE}[moduleInfo["status"]]) self.moduleReloadButton.config(state=ACTIVE) self.moduleRemoveButton.config(state=ACTIVE) else: self.selectedModule = None self.moduleNameLabel.config(text="") self.moduleAuthorHdr.config(state=DISABLED) self.moduleAuthorLabel.config(text="") self.moduleDescrHdr.config(state=DISABLED) self.moduleDescrLabel.config(text="") self.moduleClassesHdr.config(state=DISABLED) self.moduleClassesLabel.config(text="") self.moduleUrlHdr.config(state=DISABLED) self.moduleUrlLabel.config(text="") self.moduleDateHdr.config(state=DISABLED) self.moduleDateLabel.config(text="") self.moduleLicenseHdr.config(state=DISABLED) self.moduleLicenseLabel.config(text="") self.moduleEnableButton.config(state=DISABLED, text=self.ENABLE) self.moduleReloadButton.config(state=DISABLED) self.moduleRemoveButton.config(state=DISABLED) def findLocally(self): initialdir = self.cntlr.pluginDir # default plugin directory if not self.cntlr.isMac: # can't navigate within app easily, always start in default directory initialdir = self.cntlr.config.setdefault("pluginOpenDir", initialdir) filename = self.cntlr.uiFileDialog("open", parent=self, title=_("Choose plug-in module file"), initialdir=initialdir, filetypes=[(_("Python files"), "*.py")], defaultextension=".py") if filename: # check if a package is selected (any file in a directory containing an __init__.py if (os.path.isdir(os.path.dirname(filename)) and os.path.isfile(os.path.join(os.path.dirname(filename), "__init__.py"))): filename = os.path.dirname(filename) # refer to the package instead self.cntlr.config["pluginOpenDir"] = os.path.dirname(filename) moduleInfo = PluginManager.moduleModuleInfo(filename) self.loadFoundModuleInfo(moduleInfo, filename) def findOnWeb(self): url = DialogURL.askURL(self) if url: # url is the in-cache or local file moduleInfo = PluginManager.moduleModuleInfo(url) self.cntlr.showStatus("") # clear web loading status self.loadFoundModuleInfo(moduleInfo, url) def loadFoundModuleInfo(self, moduleInfo, url): if moduleInfo and moduleInfo.get("name"): self.addPluginConfigModuleInfo(moduleInfo) self.loadTreeViews() else: messagebox.showwarning(_("Module is not itself a plug-in or in a directory with package __init__.py plug-in. "), _("File does not itself contain a python program with an appropriate __pluginInfo__ declaration: \n\n{0}") .format(url), parent=self) def removePluginConfigModuleInfo(self, name): moduleInfo = self.pluginConfig["modules"].get(name) if moduleInfo: for classMethod in moduleInfo["classMethods"]: classMethods = self.pluginConfig["classes"].get(classMethod) if classMethods and name in classMethods: classMethods.remove(name) if not classMethods: # list has become unused del self.pluginConfig["classes"][classMethod] # remove class if classMethod.startswith("CntlrWinMain.Menu"): self.uiClassMethodsChanged = True # may require reloading UI elif classMethod == "ModelObjectFactory.ElementSubstitutionClasses": self.modelClassesChanged = True # model object factor classes changed elif classMethod == "DisclosureSystem.Types": self.disclosureSystemTypesChanged = True # disclosure system types changed del self.pluginConfig["modules"][name] self.pluginConfigChanged = True def addPluginConfigModuleInfo(self, moduleInfo): name = moduleInfo["name"] self.removePluginConfigModuleInfo(name) # remove any prior entry for this module self.modulesWithNewerFileDates.discard(name) # no longer has an update available self.pluginConfig["modules"][name] = moduleInfo # add classes for classMethod in moduleInfo["classMethods"]: classMethods = self.pluginConfig["classes"].setdefault(classMethod, []) if name not in classMethods: classMethods.append(name) if classMethod.startswith("CntlrWinMain.Menu"): self.uiClassMethodsChanged = True # may require reloading UI elif classMethod == "ModelObjectFactory.ElementSubstitutionClasses": self.modelClassesChanged = True # model object factor classes changed elif classMethod == "DisclosureSystem.Types": self.disclosureSystemTypesChanged = True # disclosure system types changed self.pluginConfigChanged = True def moduleEnable(self): if self.selectedModule in self.pluginConfig["modules"]: moduleInfo = self.pluginConfig["modules"][self.selectedModule] if self.moduleEnableButton['text'] == self.ENABLE: moduleInfo["status"] = "enabled" self.moduleEnableButton['text'] = self.DISABLE elif self.moduleEnableButton['text'] == self.DISABLE: moduleInfo["status"] = "disabled" self.moduleEnableButton['text'] = self.ENABLE self.pluginConfigChanged = True self.loadTreeViews() def moduleReload(self): if self.selectedModule in self.pluginConfig["modules"]: url = self.pluginConfig["modules"][self.selectedModule].get("moduleURL") if url: moduleInfo = PluginManager.moduleModuleInfo(url, reload=True) if moduleInfo: self.addPluginConfigModuleInfo(moduleInfo) self.loadTreeViews() self.cntlr.showStatus(_("{0} reloaded").format(moduleInfo.get("name")), clearAfter=5000) else: messagebox.showwarning(_("Module error"), _("File or module cannot be reloaded: \n\n{0}") .format(url), parent=self) def moduleRemove(self): if self.selectedModule in self.pluginConfig["modules"]: self.removePluginConfigModuleInfo(self.selectedModule) self.pluginConfigChanged = True self.loadTreeViews() def enableAll(self): self.enableDisableAll(True) def disableAll(self): self.enableDisableAll(False) def enableDisableAll(self, doEnable): for module in self.pluginConfig["modules"]: moduleInfo = self.pluginConfig["modules"][module] if doEnable: moduleInfo["status"] = "enabled" self.moduleEnableButton['text'] = self.DISABLE else: moduleInfo["status"] = "disabled" self.moduleEnableButton['text'] = self.ENABLE self.pluginConfigChanged = True self.loadTreeViews()
class Example(Frame): def __init__(self, parent): Frame.__init__(self, parent) self.parent = parent self.initUI() def initUI(self): self.parent.title("") self.style = Style() self.style.theme_use("clam") self.pack(fill=BOTH, expand = 1) self.labelU = Label(self, text="U:") self.labelP = Label(self, text="P:") self.entryUsername = Entry(self) self.entryUsername.config(relief='flat') self.entryUsername.focus_set() self.entryUsername.bind('<Return>', lambda event: self.entryPassword.focus_set()) self.entryPassword = Entry(self) self.entryPassword.config(relief='flat', show='•') self.entryPassword.bind('<Return>', lambda event: self.login(self.entryUsername.get(), self.entryPassword.get())) self.newbutton = Button(self, text="Login", command= lambda: self.login(self.entryUsername.get(), self.entryPassword.get())) self.newbutton.bind('<Return>', lambda event: self.login(self.entryUsername.get(), self.entryPassword.get())) self.newbutton.config(width=6) self.quitbutton = Button(self, text="Quit", command= lambda: self.quit()) self.quitbutton.config(width=6) self.mailIconRed = PhotoImage(file="mail.gif") self.labelRed = Label(self, image=self.mailIconRed) self.mailIconGray = PhotoImage(file="mail2.gif") self.labelGray = Label(self, image=self.mailIconGray) self.labelKarma = Label(self, text = '•') self.labelU.grid(row=0, column=0) self.entryUsername.grid(row=0, column=1) self.labelP.grid(row=1, column=0) self.entryPassword.grid(row=1, column=1, pady=4) self.newbutton.grid(row=2, column=1) self.quitbutton.grid(row=3, column=1, pady=4) ''' sw = self.parent.winfo_screenwidth() sh = self.parent.winfo_screenheight() w=150 h=112 x = (sw - w) / 2 y = (sh - h) / 2 self.parent.geometry('%dx%d+%d+%d' % (w, h, x, y-50)) ''' def login(self, username, password): #print('U: ' + username) self.username = username if username == '': #print('Please enter a username') self.entryUsername.focus_set() elif password == '': #print('Please enter a password') self.entryPassword.set_focus() if username != '' and password != '': #print('Attempting login for ' + username) try: self.USERAGENT = username + ' scans his inbox for new mail.' self.r = praw.Reddit(self.USERAGENT) #self.r.config._ssl_url = None self.r.login(username, password) #print('You have logged in as ' + username) self.labelU.grid_forget() self.labelP.grid_forget() self.entryUsername.grid_forget() self.entryPassword.grid_forget() self.newbutton.grid_forget() self.quitbutton.grid_forget() self.usernamelabel = Label(self, text=username) self.usernamelabel.grid(row=0, column=0, pady = 10, padx = 30) self.quitbutton.grid(row=1, column=0) self.labelKarma.grid(row = 3, column = 0) self.playedSound = 'false' self.loop() except praw.errors.InvalidUserPass: pass #print('Invalid username or password') def loop(self): while True: try: #print('Starting new search') hasmail = 'false' for msg in self.r.get_unread(limit=None): hasmail = 'true' if hasmail == 'true': #print("You've got mail!") if self.playedSound == 'false': winsound.PlaySound('pop.wav', winsound.SND_FILENAME) self.playedSound = 'true' self.labelGray.grid_forget() self.labelRed.grid(row=2, column=0) if hasmail == 'false': self.playedSound = 'false' #print('No mail!') self.labelRed.grid_forget() self.labelGray.grid(row=2, column=0) self.user = self.r.get_redditor(self.username) lkarma = str(self.user.link_karma) ckarma = str(self.user.comment_karma) lkarma = self.karmaRound(lkarma) ckarma = self.karmaRound(ckarma) karmastring = lkarma + ' • ' + ckarma self.labelKarma.config(text = karmastring) time.sleep(10) except Exception: time.sleep(10) def karmaRound(self, karma): if len(karma) > 4 and len(karma) < 7: tstring = karma[:-3] tstring2 = karma[-3:] karma = tstring + '.' + tstring2[:2] + 'K' return karma if len(karma) > 6: tstring = karma[:-6] tstring2 = karma[-6:] karma = tstring + '.' + tstring2[:2] + 'M' return karma else: return karma
class GameView(Frame): def __init__(self, ui_root, play_service): super().__init__(master=ui_root) self._ui_root = ui_root self._play_service = play_service self._current_word_var = StringVar(self) self._current_word_label = Label(master=self, textvariable=self._current_word_var) self._current_word_label.config(font=("TkDefaultFont", 24)) self._current_word_label.pack(pady=6) self._images_container = Frame(master=self) self._images_container.pack(expand=True) self._images = [] def start(self, game): self._play_service.start_game(game) self._start_round() def _start_round(self): self._images_container.destroy() self._images_container = Frame(master=self) self._images_container.pack(expand=True) self._images = [] row = Frame(master=self._images_container) row.pack(pady=3) row_count = 0 for image, index in self._play_service.get_images(): if row_count >= IMAGES_PER_ROW: row = Frame(master=self._images_container) row.pack(pady=3) row_count = 0 row_count += 1 img = ImageTk.PhotoImage(image.loaded_image) label = ImgLabel(master=row, image=img) label.bind("<Button-1>", lambda e, index=index, ctx=self: ctx.guess(index)) label.pack(side=RIGHT, padx=3) self._images.append((label, index, img)) self._update() def _update(self): self._current_word_var.set(self._play_service.get_text()) def _end_game(self): self._play_service.reset() self._ui_root.show_start_view() def guess(self, index): result = self._play_service.submit_guess(index) if result == GuessResult.INCORRECT: msg = FlashMessage(self, "Väärin", "#a00612", "#c8abb6") msg.show_timer(None) elif result == GuessResult.CORRECT_ONE: msg = FlashMessage(self, "Oikein!", "#06a012", "#ABC8B6") msg.show_timer(self._update) elif result == GuessResult.CORRECT_ROUND_COMPLETE: if self._play_service.next_round(): msg = FlashMessage(self, "Oikein!\nSeuraava kierros", "#068010", "#ABC8B6") msg.show_timer(self._start_round, 2000) else: msg = FlashMessage(self, "Oikein!\nPeli loppu", "#068010", "#ABC8B6") msg.show_timer(self._end_game, 4000)
class MainApp(): def __init__(self): self.File_name = None self.Programe_Name = "CHE-Editor" self.WDG = Tk() self.WDG.title(self.Programe_Name) self.WDG.iconbitmap("icons/icon_editor.ico") self.WDG.geometry("860x620") self.WDG.maxsize(width=1340, height=700) self.WDG.minsize(width=860, height=620) self.Main_UI() def Main_UI(self): self.MenuBar = Menu(self.WDG) #1 #MenuBar #File_menu self.File_menu = Menu(self.MenuBar, tearoff=0, title="File") self.MenuBar.add_cascade(label="File", menu=self.File_menu) #Edit_menu self.Edit_menu = Menu(self.MenuBar, tearoff=0, title="Edit") self.MenuBar.add_cascade(label="Edit", menu=self.Edit_menu) #View_menu self.View_menu = Menu(self.MenuBar, tearoff=0, title="View") self.MenuBar.add_cascade(label="View", menu=self.View_menu) #Theme_menu in View self.Theme_menu = Menu(self.View_menu, tearoff=0, title="Theme") self.View_menu.add_cascade(label="Theme", menu=self.Theme_menu) #Option_menu self.Options_menu = Menu(self.MenuBar, tearoff=0, title="Options") self.MenuBar.add_cascade(label="Options", menu=self.Options_menu) #Help_menu self.Help_menu = Menu(self.MenuBar, tearoff=0, title="Help") self.MenuBar.add_cascade(label="Help", menu=self.Help_menu) #2 #Icons Variables #Edit_Menu Icons Undo = PhotoImage(file="icons/Undo.gif") Redo = PhotoImage(file="icons/redo.gif") Paste = PhotoImage(file="icons/paste.gif") Copy = PhotoImage(file="icons/copy.gif") Cut = PhotoImage(file="icons/cut.gif") #Help_Menu_Icons Help = PhotoImage(file="icons/help.gif") About = PhotoImage(file="icons/about.gif") #File_Menu_Icons New = PhotoImage(file="icons/new.gif") Open = PhotoImage(file="icons/open.gif") Save = PhotoImage(file="icons/save.gif") Save_As = PhotoImage(file="icons/save_as.gif") Exit = PhotoImage(file="icons/exit.gif") #Appear menubar in app self.WDG.config(menu=self.MenuBar) #self.WDG.config(menu=self.IconBar) #3 #Set commands in menus #File_Menu self.File_menu.add_command(label="New", accelerator="Ctrl+N", compound="left", underline=0, command=self.New) self.File_menu.add_command(label="Open", accelerator="Ctrl+O", compound="left", underline=0, command=self.Open) self.File_menu.add_command(label="Save", accelerator="Ctrl+S", compound="left", underline=0, command=self.Save) self.File_menu.add_command(label="Save as", accelerator="Shift+Ctrl+S", compound="left", underline=0, command=self.Save_As) self.File_menu.add_separator() self.File_menu.add_command(label="Exit", accelerator="F4", compound="left", underline=0, command=self.Exit) #Edit_Menu self.Edit_menu.add_command(label="Undo", accelerator="Ctrl+Z", compound="left", underline=0, command=self.Undo) self.Edit_menu.add_command(label="Redo", accelerator='Ctrl+Y', compound='left', underline=0, command=self.Redo) self.Edit_menu.add_command(label="Select all", accelerator='Ctrl+A', compound='left', underline=0, command=self.Select) self.Edit_menu.add_command(label="Cut", accelerator='Ctrl+X', compound='left', underline=7, command=self.Cut) self.Edit_menu.add_command(label="Copy", accelerator='Ctrl+C', compound='left', underline=0, command=self.Copy) self.Edit_menu.add_command(label="Paste", accelerator='Ctrl+V', compound='left', underline=0, command=self.Paste) self.Edit_menu.add_command(label="Search", accelerator='Ctrl+F', compound='left', underline=0, command=self.Search) #Help_Menu self.Help_menu.add_command(label="Help", accelerator="F1", compound="left", underline=0, command=self.Help) self.Help_menu.add_command(label="About", compound="left", underline=0, command=self.About) #View_Menu self.Show_line_number = IntVar() self.Show_line_number.set(1) self.theme_name = StringVar() self.View_menu.add_checkbutton(label="Show Line Number", variable=self.Show_line_number) self.Highlightline = BooleanVar() self.View_menu.add_checkbutton(label='Highlight Current Line', onvalue=1, offvalue=0, variable=self.Highlightline, command=self.Toggle_highlight) self.cursorcoord = BooleanVar() self.View_menu.add_checkbutton(label='Show Cursor Location', variable=self.cursorcoord, command=self.Show_cursor_coord) self.Theme_menu.add_radiobutton(label="Default", variable=self.theme_name) #4 #add Shortcut_Bar & Row_Number_Bar #Shortcut_Bar self.Shortcut_Bar = Frame(self.WDG, height=25) self.Shortcut_Bar.pack(expand='no', fill='x') Icons = ['New', 'Open', 'Save', 'Copy', 'Cut', 'Paste', 'Undo', 'Redo'] for i, icon in enumerate(Icons): Tool_icon = PhotoImage(file='icons/{}.gif'.format(icon)) #c_var = 'self.{}'.format(icon) cmd = eval('self.{}'.format(icon)) self.Tool_bar_btn = Button(self.Shortcut_Bar, image=Tool_icon, command=cmd) self.Tool_bar_btn.image = Tool_icon self.Tool_bar_btn.pack(side='left') #Row_Number_Bar self.Row_Number_Bar = Text(self.WDG, width=3, padx=3, takefocus=0, border=0, background='khaki', state='disabled', wrap='none') self.Row_Number_Bar.pack(side='left', fill='y') #5 #add Content_Text self.Content_Text = Text(self.WDG, wrap='word', undo=1) self.Content_Text.pack(expand='yes', fill='both') self.Content_Text.tag_configure('active_line', background='ivory2') self.Scroll_Bar = Scrollbar(self.Content_Text) self.Content_Text.configure(yscrollcommand=self.Scroll_Bar.set) self.Scroll_Bar.config(command=self.Content_Text.yview) self.Scroll_Bar.pack(side='right', fill='y') #6 #add_Cursor_Coord_Bar self.Cursor_Coord_Bar = Label(self.Content_Text, text='Row: 1 | Column: 1') self.Cursor_Coord_Bar.pack(fill=None, expand='no', side='right', anchor='se') #7 #Binding self.Content_Text.bind("<Control-o>", self.Open) self.Content_Text.bind("<Control-O>", self.Open) self.Content_Text.bind("<Control-s>", self.Save) self.Content_Text.bind("<Control-S>", self.Save) self.Content_Text.bind("<Shift-Control-KeyPress-s>", self.Save_As) self.Content_Text.bind("<Shift-Control-KeyPress-S>", self.Save_As) self.Content_Text.bind("<Control-n>", self.New) self.Content_Text.bind("<Control-N>", self.New) self.Content_Text.bind("<Control-z>", self.Undo) self.Content_Text.bind("<Control-Z>", self.Undo) self.Content_Text.bind("<Control-y>", self.Redo) self.Content_Text.bind("<Control-Y>", self.Redo) self.Content_Text.bind("<Control-x>", self.Cut) self.Content_Text.bind("<Control-X>", self.Cut) self.Content_Text.bind("<Control-a>", self.Select) self.Content_Text.bind("<Control-A>", self.Select) self.Content_Text.bind("<Control-c>", self.Copy) self.Content_Text.bind("<Control-C>", self.Copy) self.Content_Text.bind("<Control-v>", self.Paste) self.Content_Text.bind("<Control-V>", self.Paste) self.Content_Text.bind("<Control-f>", self.Search) self.Content_Text.bind("<Control-F>", self.Search) self.Content_Text.bind("<Any-KeyPress>", self.Content_changed) self.WDG.bind_all("<KeyPress-F1>", self.Help) self.WDG.bind_all("<KeyPress-F4>", self.Exit) #8 #Built In Finctions #File_Menu_Functions def New(self, event=None): self.Content_Text.delete(1., 'end') self.WDG.title('{} - {}'.format('Untitled', self.Programe_Name)) ## def Open(self, event=None): self.Open_file_name = filedialog.askopenfilename( defaultextension=".txt", filetypes=[("All Files", "*.*"), ("Text Documents", "*.txt")]) if self.Open_file_name: self.File_name = self.Open_file_name self.WDG.title("{} - {}".format(os.path.basename(self.File_name), self.Programe_Name)) self.Content_Text.delete(1.0, 'end') with open(self.File_name) as _File: self.Content_Text.insert(1.0, _File.read()) ## def Save(self, event=None): if not self.File_name: self.Save_As() else: self.Write_to_file(self.File_name) return "break" ## def Save_As(self, event=None): self.Save_file_name = filedialog.asksaveasfilename( defaultextension='.txt', filetypes=[('All Files', '*.*'), ('Text Documents', '*.txt')]) if self.Save_file_name: self.File_name = self.Save_file_name self.Write_to_file(self.File_name) self.WDG.title('{} - {}'.format(os.path.basename(self.File_name), self.Programe_Name)) return "break" ## def Write_to_file(self, filename): try: self.content = self.Content_Text.get(1.0, 'end') with open(self.File_name, 'w') as the_file: the_file.write(self.content) except IOError as er: print(er) ## def Exit(self, event=None): self.msg_exit = messagebox.askyesno('Exit Editor', 'Do you want to exit?') if self.msg_exit: self.WDG.destroy() #Edit_Menu_Functions ## def Select(self, event=None): self.Content_Text.tag_add("sel", 1.0, "end") print("Done1") return "breake" ## def Cut(self, event=None): self.Content_Text.event_generate("<<Cut>>") return "breake" ## def Copy(self, event=None): self.Content_Text.event_generate("<<Copy>>") return "breake" ## def Paste(self, event=None): self.Content_Text.event_generate("<<Paste>>") return "breake" ## def Undo(self, event=None): self.Content_Text.event_generate("<<Undo>>") return "breake" ## def Redo(self, event=None): self.Content_Text.event_generate("<<Redo>>") return "breake" ## def Search(self, event=None): self.Search_Window = Toplevel(self.WDG) self.Search_Window.title("Search About...") self.Search_Window.transient(self.WDG) self.Search_Window.resizable(False, False) self.S_lbl_1 = Label(self.Search_Window, text='Search About :') self.S_lbl_1.grid(row=0, column=0, sticky='e') self.S_ent_1 = Entry(self.Search_Window, width=28) self.S_ent_1.grid(row=0, column=1, padx=2, pady=2, sticky='we') self.S_ent_1.focus_set() Ignore_case_value = IntVar() self.S_chk_1 = Checkbutton(self.Search_Window, text='Ignor Case', variable=Ignore_case_value) self.S_chk_1.grid(row=1, column=1, padx=2, pady=2, sticky='e') self.S_btn_1 = Button( self.Search_Window, text='Find', underline=0, command=lambda: self.Search_results(self.S_ent_1.get( ), Ignore_case_value.get(), self.Content_Text, self.Search_Window, self.S_ent_1)) self.S_btn_1.grid(row=0, column=2, padx=2, pady=2, sticky='e' + 'w') self.S_btn_2 = Button(self.Search_Window, text='Cancel', underline=0, command=self.Close_Search_Window) self.S_btn_2.grid(row=1, column=2, padx=2, pady=2, sticky='e' + 'w') ## def Search_results(self, Keyword, IfIgnoreCase, Content, Output, Input): Content.tag_remove('match', '1.0', 'end') matches_found = 0 if Keyword: start_pos = '1.0' while True: start_pos = Content.search(Keyword, start_pos, nocase=IfIgnoreCase, stopindex='end') if not start_pos: break end_pos = "{} + {}c".format(start_pos, len(Keyword)) Content.tag_add('match', start_pos, end_pos) matches_found += 1 start_pos = end_pos Content.tag_config('match', foreground='red', background='yellow') Input.focus_set() Output.title("{} matches found".format(matches_found)) ## def Close_Search_Window(self): self.Content_Text.tag_remove('match', '1.0', 'end') self.Search_Window.destroy() #self.Search_Window.protocol('WM_DELETE_WINDOW',self.Close_Search_Window) return "break" #View_Menu_Functions ## def Content_changed(self, event=None): self.Update_line_numbers() self.Update_cursor_coord() ## def Get_line_numbers(self, event=None): self.Number = "" if self.Show_line_number.get(): self.Row, self.Column = self.Content_Text.index('end').split('.') for i in range(1, int(self.Row)): self.Number += str(i) + "\n" return self.Number ## def Update_line_numbers(self): self.Line_Number = self.Get_line_numbers() self.Row_Number_Bar.config(state='normal') self.Row_Number_Bar.delete(1.0, 'end') self.Row_Number_Bar.insert(1.0, self.Line_Number) self.Row_Number_Bar.config(state='disabled') ## def Toggle_highlight(self, event=None): if self.Highlightline.get(): self.Highlight_line() else: self.Undo_highlight() ## def Highlight_line(self, interval=100): self.Content_Text.tag_remove('active_line', 1.0, 'end') self.Content_Text.tag_add('active_line', "insert linestart", "insert lineend+1c") self.Content_Text.after(interval, self.Toggle_highlight) ## def Undo_highlight(self): self.Content_Text.tag_remove('active_line', 1.0, 'end') ## def Show_cursor_coord(self): self.cursor_coord_checked = self.cursorcoord.get() if self.cursor_coord_checked: self.Cursor_Coord_Bar.pack(expand='no', fill=None, side='right', anchor='se') else: self.Cursor_Coord_Bar.pack_forget() ## def Update_cursor_coord(self): self.Row_2, self.Column_2 = self.Content_Text.index('insert').split( '.') self.row_num, self.col_num = str(int( self.Row_2)), str(int(self.Column_2) + 1) self.Coord = "Row: {} | Column: {}".format(self.row_num, self.col_num) self.Cursor_Coord_Bar.config(text=self.Coord) #Help_Menu_Functions ## def About(self, event=None): messagebox.showinfo( 'About', '{} {}'.format(self.Programe_Name, '\nDeveloped by \n TaReK')) ## def Help(self, event=None): messagebox.showinfo('Help', 'Text Editor building in python', icon='question')
class TtkScale(Scale): def __init__(self, parent, length=0, from_=0, to=255, orient='vertical', variable=0, digits=None, tickinterval=None, command=None, style=None, showvalue=True, resolution=1): self.from_ = from_ self.to = to self.variable = variable self.length = length self.command = command self.parent = parent super().__init__(parent, length=length, from_=from_, to=to, orient=orient, variable=variable, command=command, style=style) self.digits = digits self.tickinterval = tickinterval self.showvalue = showvalue self.resolution = resolution # set sliderlength st = Style(self) self.bw_val = bw_val = st.lookup('Vertical.Scale.trough', 'borderwidth') self.sliderlength = sliderlength = 32 if showvalue: self.configure(command=self.display_value) def_font = font.nametofont('TkDefaultFont') # if from_ more than to swap values if from_ < to: pass else: from_, to = to, from_ data = np.arange(from_, (to + 1 if tickinterval >= 1 else to + tickinterval), tickinterval) self.data = data = np.round(data, 1) range_vals = tuple(data) len_rvs = len(range_vals) lspace = def_font.metrics('linespace') len_rvs = len(range_vals) data_size = len_rvs * lspace space_size = len_rvs * 3 sizes = data_size + space_size min_len = (sizes if sizes % 50 == 0 else sizes + 50 - sizes % 50) self.len_val = len_val = min_len if length < min_len else length self.configure(length=len_val) self.rel_min = rel_min = (sliderlength / 2 + bw_val) / len_val self.rel_max = rel_max = 1 - (sliderlength / 2 - bw_val) / len_val if range_vals[-1] == to: pass else: max_rv = range_vals[-1] self.mult_y = mult_y = ((max_rv - from_) * rel_max / (to - from_)) self.bind("<Button-1>", self.resolve) self.build(from_, to, rel_min, rel_max, range_vals, len_rvs) def build(self, from_, to, rel_min, rel_max, range_vals, len_rvs): for i, rv in enumerate(range_vals): item = Label(self.parent, text=rv) item.place( in_=self, bordermode='outside', rely=(rel_min + i / (len_rvs - 1) * ((rel_max if range_vals[-1] == to else self.mult_y) - rel_min)), relx=1, anchor='w') if self.showvalue: self.disp_lab = Label(self.parent, text=self.get()) rel_y = self.convert_to_rely(float( self.get())) #, textvariable = self.act_val) self.disp_lab.place(in_=self, bordermode='outside', rely=rel_y, relx=0, anchor='e') def convert_to_rely(self, curr_val): return ((curr_val - self.from_) * (self.rel_max - self.rel_min) / (self.to - self.from_) + self.rel_min) def convert_to_acty(self, curr_val): y_max = self.rel_max * self.len_val y_min = self.rel_min * self.len_val return ((curr_val - self.from_) * (y_max - y_min) / (self.to - self.from_) + y_min) def display_value(self, value): # position (in pixel) of the center of the slider rel_y = self.convert_to_rely(float(value)) self.disp_lab.config(text=value) # text="" self.disp_lab.place_configure(rely=rel_y) digits = self.digits self.disp_lab.configure(text=f'{float(value):.{dig_val}f}') # if your python is not 3.6 or above use the following 2 lines # instead of the line above #my_precision = '{:.{}f}'.format #self.disp_lab.configure(text=my_precision(float(value), digits)) def resolve(self, evt): resolution = self.resolution if resolution < 1 or self.tickinterval < 1: pass else: value = self.get() curr_y = self.convert_to_acty(value) if evt.y < curr_y - self.sliderlength / 2: self.set(value - resolution + 1) elif evt.y > curr_y + self.sliderlength / 2: self.set(value + resolution - 1)
class MainGUI: def __init__(self, master): """ Constructor: Creates the GUI and creates a socket Args: self: calling object master: parent widget Returns: void """ # sets host and port of server self.host = '10.18.207.18' self.port = 9998 # sets up empty var for ticker self.tkr = '' # sets up prediction variable self.prediction = 0 self.master = master master.title('Stock Predictor') master.geometry('800x600') # creates label self.lbl = Label(master, text='Input Stock Ticker') self.lbl.pack(side=TOP) # creates text field self.txt = Entry(master, width=10) self.txt.pack(side=TOP) # creates submission button self.btn = Button(master, text='Submit', command=self.clicked_tkr) self.btn.pack(side=TOP) # creates prediction explicit label self.p_lbl = Label(master, text='Prediction(1 day in the future): ') self.p_lbl.pack(side=TOP) # creates prediction output label self.p_out_lbl = Label(master, text=self.get_prediction()) self.p_out_lbl.config(font=17) self.p_out_lbl.pack(side=TOP) def disp_graph(self, wait=False): """ Displays the image stored as imgFile.png to the GUI Args: self: calling object wait: boolean True if waiting for image False if not Returns: void """ try: if wait: img = Image.open('waitImg.png') else: img = Image.open('imgFile.png') render = ImageTk.PhotoImage(img) # create image label img = Label(self.master, image=render) img.image = render img.place(x=95, y=110) except OSError as OSE: messagebox.showinfo('Graph Retrieval Failed', 'The graph requested was not received correctly. Please ' 'submit the request again.') def clicked_tkr(self): """ Gathers the input from self.txt, verifies it, then requests a prediction and a graph. It then finally calls disp_graph(). Also handles server offline and invalid input cases. Args: self: calling object Returns: void """ ticker = "" try: if self.txt.get().strip(): ticker = self.txt.get().strip() else: raise ValueError('Empty string') self.update_prediction_out('Please wait. This could take up to 1 minute.') client_socket = StockPSocket(self.host, self.port) if client_socket.validate(ticker + 'v') == 'error': client_socket.close() self.update_prediction_out('Invalid input') raise ValueError() else: self.tkr = ticker self.disp_graph(wait=True) # gets predicted value of stock client_socket = StockPSocket(self.host, self.port) client_socket.send_request(self.tkr + 'p') prediction = client_socket.rec_pred() client_socket.close() self.update_prediction_out(prediction) # after Ryan finishes lstm prediction # gets graph of stock client_socket = StockPSocket(self.host, self.port) client_socket.send_request(self.tkr + 'g') client_socket.receive() client_socket.close() self.disp_graph() except ValueError as VE: messagebox.showinfo('Invalid Ticker', 'Please enter a proper stock ticker. If you are trying to get data ' 'about a market index prefix the ticker with a ^ (ie. ^dji).') except ConnectionRefusedError as CRE: messagebox.showinfo('Server Offline', 'Sorry for the inconvenience, but this service is not available ' 'right now.') def set_prediction(self, prediction): """ Updates the prediction variable Args: self: calling object prediction: int updated value Returns: void """ self.prediction = prediction def get_prediction(self): """ Returns the current value stored in prediction Args: self: calling object Returns: prediction: int """ return self.prediction def update_prediction_out(self, prediction): """ Updates the prediction label Args: self: calling object prediction: int value for updated presiction Returns: void """ self.set_prediction(prediction) self.p_out_lbl['text'] = self.get_prediction() self.p_out_lbl.update()
class retailPage(Frame): ''' the main page that actually branches into 2 seperate frames for buying and selling this frame provides the use with the ''' def __init__(self, parent, main, **kw): Frame.__init__(self, parent, **kw) self.main = main self.Head = Label(font=MED_FONT) self.retail_back_b = Button(text='BACK', command=self.back_fb) self.stock_name = StringVar() self.stock_name_ = '' self.stock_name_c = Combobox(textvariable=self.stock_name) self.stock_name_l = Label(text='Stock name: ') self.amount = Entry() self.amount_l = Label(text='Number of stocks :') self.check_avail_b = Button(text='Check') self.cost_l = Label(text='Cost: ') self.cost = Label() self.buy_stock_b = Button(text='BUY Stock') self.sellp_l = Label(text='Current Selling Price: ') self.profit_l = Label(text='PROFIT/LOSS') self.sell_stock_b = Button(text='SELL Stock') self.page = None def showItems(self, main): self.Head.grid(column=0, row=0, columnspan=2) self.Head.configure(text='logged in as %s' % main.present_user) if self.page == 'b': self.buy() elif self.page == 's': self.sell() def hideItems(self, main): self.Head.grid_forget() def buy(self): '''This function creates the buy window ''' self.retail_back_b.grid(column=1, row=5) self.retail_back_b.config(command=self.back_fb) self.stock_name_l.grid(column=0, row=1) self.stock_name_c.grid(column=1, row=1) self.stock_name_c.config(values=self.main.shares_dict.keys()) self.amount_l.grid(column=0, row=2) self.amount.grid(column=1, row=2) self.check_avail_b.config(command=self.check_avail_buy) self.check_avail_b.grid(column=0, row=3) self.cost_l.grid(column=0, row=4, columnspan=2) self.buy_stock_b.config(command=self.buy_stock, text='Buy Stock', state='disabled') self.buy_stock_b.grid(column=0, row=5) def sell(self): '''This function creats the sell window''' self.retail_back_b.grid(column=1, row=6) self.retail_back_b.config(command=self.back_fs) self.check_avail_b.config(command=self.check_avail_sell) self.stock_name_l.grid(column=0, row=1) self.stock_name_c.grid(column=1, row=1) self.stock_name_c.config(values=self.main.shares_dict.keys()) self.amount_l.grid(column=0, row=2) self.amount.grid(column=1, row=2) self.check_avail_b.grid(column=0, row=3) self.sellp_l.grid(column=0, row=4, columnspan=2) self.profit_l.grid(column=0, row=5, columnspan=2) self.sell_stock_b.config(command=self.sell_stock, state='disabled', text='Check') self.sell_stock_b.grid(column=0, row=6) def back_fb(self): '''Back from buy i.e. removes all the items needed to make buy''' self.retail_back_b.grid_forget() self.Head.grid(column=0, row=0, columnspan=2) self.stock_name_l.grid_forget() self.stock_name_c.grid_forget() self.amount_l.grid_forget() self.amount.grid_forget() self.check_avail_b.grid_forget() self.cost_l.grid_forget() self.buy_stock_b.grid_forget() self.buy_stock_b.config(state='disabled') self.main.show_frame(VIEW_STOCK, RETAIL_PAGE) self.stock_name.set('') self.amount.delete(0, END) def back_fs(self): ''' Back from sell i.e. removes all the items needed to make it sell window''' self.Head.grid(column=0, row=0, columnspan=2) self.retail_back_b.grid_forget() self.check_avail_b.grid_forget() self.stock_name_l.grid_forget() self.stock_name_c.grid_forget() self.amount_l.grid_forget() self.amount.grid_forget() self.sellp_l.grid_forget() self.profit_l.grid_forget() self.sell_stock_b.grid_forget() self.main.show_frame(VIEW_STOCK, RETAIL_PAGE) self.stock_name.set('') self.amount.delete(0, END) self.check_avail_b.grid_forget() def check_avail_buy(self): ''' Performs a check whether the number of shares requisted are available or not and then check whether the person has the required amounts of fund or not for the transaction to go through''' name = self.stock_name.get() l2 = self.main.accounts[self.main.present_user] if name in self.main.shares_dict.keys(): li = self.main.shares_dict[name] else: self.stock_name.delete(0, END) showinfo(meassage='Enter a Valid Stock name') available_num = int(li['tot_amount']) - int(li['tot_sold']) req = int(self.amount.get()) cost = req * int(li['cost']) if req < 0: showinfo(message='Enter a Valid amount') elif req > available_num: showinfo(message='Enter an amount less than ' + str(available_num)) elif cost > int(l2['balance']): showinfo(message='You have only %s in you account' % l2['balance']) else: self.cost_l.config(text='Cost: \t' + li['cost'] + '*' + str(req) + '=' + str(cost)) self.buy_stock_b.config(state='normal') def check_avail_sell(self): ''' Performs a check whether the user has enough stocks to sell''' name = self.stock_name.get() if name in self.main.shares_dict.keys(): li = self.main.shares_dict[name] else: self.stock_name.delete(0, END) showinfo(message='Enter a Valid Stock name') req = int(self.amount.get()) if req < 0: showinfo(message='Please Enter a Valid amount') self.amount.delete(0, END) li = self.main.p_user_dict ok = False for i in li: if name == i['name']: ok = True buff = i if req > int(buff['tot_owned']): showinfo(message='You dont have that many stocks try less than ' + buff['tot_owned']) self.amount.delete(0, END) cost = self.main.shares_dict[name]['cost'] tot_cost = req * int(cost) try: spent = req * float(buff['money_spent']) / int(buff['tot_owned']) except: spent = 0 pol = tot_cost - spent if pol >= 0: self.profit_l.config() elif pol < 0: self.profit_l.config() if req <= int(buff['tot_owned']): self.sellp_l.config(text='Current Selling Price: \t' + cost) self.profit_l.config(text="PROFIT-LOSS: \t" + str(pol)) self.sell_stock_b.config(command=self.sell_stock, text='Sell Stock') showinfo(message= 'Everthing is ok, \nClicking Sell will execute the trade') self.sell_stock_b.config(state='normal') def buy_stock(self): '''Finally Executes the transaction and asks the user for conformation one last time''' name = self.stock_name.get() li = self.main.shares_dict[name] for i in range(len(self.main.p_user_dict)): if name == self.main.p_user_dict[i]['name']: index = i req = int(self.amount.get()) tot_cost = req * int(li['cost']) self.main.shares_dict[name]['tot_sold'] = str( int(self.main.shares_dict[name]['tot_sold']) + req) self.main.p_user_dict[index]['tot_owned'] = str( int(self.main.p_user_dict[index]['tot_owned']) + req) self.main.p_user_dict[index]['money_spent'] = str( int(self.main.p_user_dict[index]['money_spent']) + tot_cost) self.main.users_dict[ self.main.present_user][index] = self.main.p_user_dict[index] balance = int(self.main.accounts[self.main.present_user]['balance']) self.main.accounts[self.main.present_user]['balance'] = str(balance - tot_cost) self.cost_l.config(text='Cost: ') showinfo( message='You have just bought %s of the stock %s at the price %s' % (str(req), name, str(tot_cost))) self.stock_name.set('') self.main.show_frame(VIEW_STOCK, RETAIL_PAGE) self.back_fb() def sell_stock(self): '''Asks the user for conformation and then completes the transaction of selling, at this point the profit field is also updated''' name = self.stock_name.get() req = int(self.amount.get()) li = self.main.p_user_dict for i in range(len(li)): if name == li[i]['name']: ok = True buff = i tot_cost = req * int(self.main.shares_dict[name]['cost']) try: spent = req * float( self.main.p_user_dict[buff]['money_spent']) / int( self.main.p_user_dict[buff]['tot_owned']) except ZeroDivisionError: spent = 0 self.main.shares_dict[name]['tot_sold'] = str( int(self.main.shares_dict[name]['tot_sold']) - req) self.main.p_user_dict[buff]['tot_owned'] = str( int(self.main.p_user_dict[buff]['tot_owned']) - req) pol = tot_cost - spent diff = int(self.main.p_user_dict[buff]['money_spent']) - tot_cost self.main.p_user_dict[buff]['money_spent'] = str( diff) if diff > 0 else '0' self.main.users_dict[self.main.present_user] = self.main.p_user_dict profit = int(self.main.accounts[self.main.present_user]['profit']) self.main.accounts[self.main.present_user]['profit'] = str( int(profit + pol)) balance = int(self.main.accounts[self.main.present_user]['balance']) self.main.accounts[self.main.present_user]['balance'] = str(balance + tot_cost) self.retail_back_b.grid_forget() self.profit_l.config(text='PROFIT/LOSS: ') self.sellp_l.config(text='Current selling price: ') self.main.show_frame(VIEW_STOCK, RETAIL_PAGE) self.back_fs()
class App(Frame): # Fields root = None itemList = None statusLabel = None image_width = 202 image_height = 360 imageLabel = None def __init__(self, root): super().__init__() self.initUI() self.root = root def initUI(self): # TitleBar self.master.title("Easy Checkout") self.pack(fill=BOTH, expand=True) # Stretch self.columnconfigure(3, weight=1) self.columnconfigure(0, pad=7) self.rowconfigure(3, weight=1) self.rowconfigure(5, pad=7) # Row0 : Labels for Sections cmd = Label(self, text="Commands") cmd.grid(sticky=W, pady=4, padx=5, row=0, column=0) pic = Label(self, text="Picture") pic.grid(sticky=W, pady=4, padx=5, row=0, column=1) items = Label(self, text="Items") items.grid(sticky=W, pady=4, padx=5, row=0, column=3) self.statusLabel = Label( self, text="Hello!\nThis is\nEasyCheckout\n\nPress Activate\nto Start") self.statusLabel.grid(sticky=W, pady=4, padx=5, row=3, column=0) self.itemList = Listbox(self) self.itemList.grid(row=1, column=3, rowspan=4, padx=5, sticky=E + W + S + N) #Buttons abtn = Button(self, text="Activate", command=lambda: easycheckout.run(self)) abtn.grid(row=1, column=0) qbtn = Button(self, text="Quit", command=self.quit) qbtn.grid(row=2, column=0, pady=4) clearbtn = Button(self, text="Clear", command=self.clearItem) clearbtn.grid(row=5, column=0, padx=5) obtn = Button(self, text="OK", command=self.changeImage) obtn.grid(row=5, column=3) #Pictures path = "result.jpg" pil_img = Image.open(path) #Pictures : Resize to Show w, h = pil_img.size resizedImg = self.resize(w, h, self.image_width, self.image_height, pil_img) img = ImageTk.PhotoImage(resizedImg) self.imageLabel = Label(self, image=img) self.imageLabel.image = img self.imageLabel.grid(row=1, column=1, columnspan=2, rowspan=4, sticky=E + W + S + N, padx=5) # METHODS def resize(self, w, h, w_box, h_box, pil_image): ''' resize a pil_image object so it will fit into a box of size w_box times h_box, but retain aspect ratio ''' f1 = 1.0 * w_box / w # 1.0 forces float division in Python2 f2 = 1.0 * h_box / h factor = min([f1, f2]) #print(f1, f2, factor) # test # use best down-sizing filter width = int(w * factor) height = int(h * factor) return pil_image.resize((width, height), Image.ANTIALIAS) # changeImage NEEDTOBE IMPLEMENTED def changeImage(self, path='test.png', resize=True): pil_img = Image.open(path) if (resize): #Pictures : Resize to Show w, h = pil_img.size resizedImg = self.resize(w, h, self.image_width, self.image_height, pil_img) else: resizedImg = pil_img img = ImageTk.PhotoImage(resizedImg) self.imageLabel.config(image=img) self.imageLabel.image = img # Insert Item in the ListBox def insertItem(self, item): self.itemList.insert(END, item) # Delete Item(s) in the ListBox def clearItem(self): selection = self.itemList.curselection() if (len(selection) == 0): self.itemList.delete(0, self.itemList.size()) else: idx = selection[0] self.itemList.delete(idx) # Quit Window def quit(self): self.root.quit() # ChangeStatus Text def changeStatus(self, status): self.statusLabel.config(text=status) # Update TK def update(self): self.root.update()
class SolutionTabFrame(Frame): ''' This class is responsible for displaying solution on the screen. It extends Frame class. Attributes: parent (Tk object that can contain Frame): parent that can contain Frame, MUST implement method change_solution_tab_name(str). data_from_file_lbl (Label): label that contains file name with data if specified. solution_tab (SolutionFrameWithText): notebook with tabs describing solution. model_solutions (list of Solution): list with one or more solutions that have been generated after running algorithm. param_strs (list of str): list with strings that should appear before printing every solution from model_solutions. ranks (list of list of int): list of ranks corresponding to every solution from model_solutions, ranks are generated by peel-the-onion algorithm. categorical (str): name of the categorical variable used in categorical analysis. progress_bar (Progressbar): progress bar to show how solution is loaded or saved to file. status_lbl (Label): label for displaying solution status. solution_format_var (IntVar): IntVar object that tracks which file format is chosen for solution. ''' def __init__(self, parent, *args, **kw): super().__init__(parent, *args, **kw) self.parent = parent self.data_from_file_lbl = None self.solution_tab = None self.model_solutions = None self.param_strs = None self.ranks = None self.params = None self.categorical = None self.run_date = None self.total_seconds = 0 self.progress_bar = None self.status_lbl = None self.solution_format_var = IntVar() self.create_widgets() def create_widgets(self): ''' Creates appropriate widgets on this frame. ''' self.columnconfigure(0, weight=1) self.rowconfigure(3, weight=1) frame_for_save_btn = Frame(self) frame_for_save_btn.columnconfigure(1, weight=1) self.status_lbl = Label(frame_for_save_btn, text='') self.status_lbl.grid(row=0, column=1, sticky=N+W) save_solution_btn = Button(frame_for_save_btn, text='Save solution', command=self.on_save_solution) save_solution_btn.grid(row=1, column=0, sticky=W+N, padx=5, pady=5) self.progress_bar = Progressbar(frame_for_save_btn, mode='determinate', maximum=100) self.progress_bar.grid(row=1, column=1, sticky=W+E, padx=10, pady=5) frame_for_save_btn.grid(sticky=W+N+E+S, padx=5, pady=5) frame_for_btns = Frame(self) self._create_file_format_btn('*.xlsx', 1, frame_for_btns, 0) self._create_file_format_btn('*.xls', 2, frame_for_btns, 1) self._create_file_format_btn('*.csv', 3, frame_for_btns, 2) self.solution_format_var.set(1) frame_for_btns.grid(row=1, column=0, sticky=W+N+E+S, padx=5, pady=5) self.data_from_file_lbl = Label(self, text=TEXT_FOR_FILE_LBL, anchor=W, justify=LEFT, wraplength=MAX_FILE_PARAMS_LBL_LENGTH) self.data_from_file_lbl.grid(row=2, column=0, padx=5, pady=5, sticky=W+N) self.solution_tab = SolutionFrameWithText(self) self.solution_tab.grid(row=3, column=0, sticky=W+E+S+N, padx=5, pady=5) def _create_file_format_btn(self, btn_text, var_value, parent, column): ''' Creates and grids Radiobutton used for choosing solution file format. Args: btn_text (str): text displayed next to the Radiobutton. var_value (int): value of the IntVar associated with this Radiobutton. parent (Tk object): parent of this Radiobutton. column (int): column index where this Radiobutton should be gridded. ''' sol_format_btn = Radiobutton(parent, text=btn_text, variable=self.solution_format_var, value=var_value) sol_format_btn.grid(row=2, column=column, sticky=W+N, padx=2) def on_save_solution(self): ''' Saves solution to file. This method is called when save solution button is pressed. If there is a solution, this method will ask user to provide a file name where solution should be stored. If a valid name is provided, solution is saved to that file. Allowed file formats are: .xls and .xlsx. Default file extension is .xlsx. If the user checked 'csv' as solution output format, then the user will be asked to choose a directory where all csv files will be written. ''' if self.model_solutions is not None: assert(self.param_strs is not None) if (self.solution_format_var.get() == 1 or self.solution_format_var.get() == 2): file_name = self.ask_file_name_to_save( self.solution_format_var.get()) dir_name = '' else: dir_name = askdirectory() file_name = '' if file_name or dir_name: print(file_name) self.status_lbl.config(text='Saving solution to file...') if file_name.endswith('.xls'): work_book = xlwt.Workbook() elif file_name.endswith('.xlsx'): work_book = XlsxWorkbook() else: # all not supported formats will be written to csv assert(dir_name) work_book = TxtWriter(dir_name) writer = XLSWriter(self.params, work_book, self.run_date, self.total_seconds, ranks=self.ranks, categorical=self.categorical) nb_models = len(self.model_solutions) # +1 for parameters sheet, it is stored separately nb_sheets = len(writer.worksheets) + 1 progress_recorder = GuiProgress(self.progress_bar, nb_models, nb_sheets) try: for count, sol in enumerate(self.model_solutions): writer.write_data(sol, self.param_strs[count], progress_recorder) work_book.save(file_name) except ValueError: # can happen if maximum number of rows is exceeded self.status_lbl.config( text='File is too large for xls format,' ' it will be saved to csv instead') work_book = TxtWriter(os.path.splitext(file_name)[0]) writer = XLSWriter(self.params, work_book, self.run_date, self.total_seconds, ranks=self.ranks, categorical=self.categorical) progress_recorder.set_position(0) for count, sol in enumerate(self.model_solutions): writer.write_data(sol, self.param_strs[count], progress_recorder) work_book.save(file_name) progress_recorder.set_position(100) self.parent.change_solution_tab_name('Solution') self.status_lbl.config(text='Solution saved') def ask_file_name_to_save(self, ext_code): ''' Calls asksaveasfilename dialogue to ask the user where file should be saved. If file without extension is entered, default extension will be used (.xlsx). This method is used to mock this object for unit tests. Args: ext_code (int): code for file extension 1 - xlsx, 2 - xls. ''' if ext_code == 1: filetype = SOLUTION_XLSX_FILE else: filetype = SOLUTION_XLS_FILE return asksaveasfilename(filetypes=filetype, defaultextension='xlsx') def show_solution(self, solutions, params, param_strs, run_date, total_seconds, ranks=None, categorical=None): ''' Displays solution on the screen. Args: solutions (list of Solution): list of solutions (might contain just one solution) that have been generated after running algorithm. params (Parameters): object with parameters that will be written to file on the Parameters page. param_strs (list of str): list with strings that should appear before printing every solution from model_solutions. ranks (list of list of int): list of ranks corresponding to every solution from model_solutions, ranks are generated by peel-the-onion algorithm. categorical (str): name of the categorical variable used in categorical analysis. ''' self.status_lbl.config(text='') self.model_solutions = solutions self.param_strs = param_strs self.ranks = ranks self.params = params self.categorical = categorical self.run_date = run_date self.total_seconds = total_seconds self.status_lbl.config(text='Loading solution...') self.solution_tab.show_solution(solutions, params, param_strs, run_date, total_seconds, ranks, categorical) self.parent.change_solution_tab_name('Solution*') self.status_lbl.config(text='Solution loaded') def update_data_file_name(self, new_data_file_name): ''' Updates label with data file name. Args: new_data_file_name (str): new value of the data file name ''' self.data_from_file_lbl.config(text=TEXT_FOR_FILE_LBL + new_data_file_name)
class Application(Frame): """The main Tk application, a simple dialog.""" def __init__(self, master=None): super().__init__(master) self.badge = None self.grid() self.columnconfigure(0, minsize=200) self.columnconfigure(1, minsize=200) self.rowconfigure(0, minsize=300) self.rowconfigure(3, minsize=30) self.create_widgets() self.connect() def create_widgets(self): """Sets up dialog elements.""" self.select = tix.FileSelectBox(self, browsecmd=self.on_file_selected, pattern="*.fs", directory="forth") # self.select["textVariable"] = self.forth_file self.select.grid(row=0, columnspan=2, sticky='n'+'w'+'e') self.connect_btn = Button(self, text="Connect", command=self.toggle_connect) self.connect_btn.grid(row=1, column=0, columnspan=2) self.exec_btn = Button(self, text="Execute", command=self.send_file) self.exec_btn.state(["disabled"]) self.exec_btn.grid(row=2, column=0, sticky='w' + 'e', padx=5, pady=3) self.quit = Button(self, text="QUIT", command=self.master.destroy) self.quit.grid(row=2, column=1, sticky='w' + 'e', padx=5, pady=3) self.status_panel = Frame(self, relief="groove", borderwidth=3) self.status_panel.grid(row=3, columnspan=2, sticky='nwse') self.connect_status = Label(self.status_panel, text="Not Connected") self.connect_status.grid(row=0, padx=5, pady=5, sticky="w") if self.badge is not None: self.connect_btn.state(["disabled"]) self.connect_status.config(text="Connected: " + self.badge.os_device) def send_file(self, _retry=False): """Send the selected file to the badge.""" if self.badge: try: # oddly, very first set LED seems to not set correct color self.badge.led(0, 0, 128) self.badge.led(0, 0, 128) with open(self.select.cget("value"), 'r') as forthin: self.badge.forth_run(forthin.read()) time.sleep(1) # because forth_run() may be too fast self.badge.led(0, 128, 0) except IOError: if not _retry: self.connect() self.send_file(True) else: raise def toggle_connect(self): "If connected, disconnect, otherwise connect." if self.connect_btn.cget("text") == "Connect": self.connect() else: self.disconnect() def disconnect(self): "Disconnect from current badge." isinstance(self.badge, Badge) self.badge.close() self.badge = None self.connect_btn.config(text="Connect") self.connect_status.config(text="Not connected.") self.exec_btn.state(["disabled"]) def connect(self): """Attempt to connect to a badge; toggle Connect button if successful.""" try: self.badge = Badge() self.connect_status.config(text="Connected: " + self.badge.os_device) self.connect_btn.config(text="Disconnect") # enable "Execute" if file is selected self.on_file_selected(self.select.cget("value")) except BadgeSerialException: self.connect_status.config(text="Not connected") def on_file_selected(self, selected_file): """Respond to user selection of file by enabling the Execute button.""" if Path(selected_file).is_file: self.exec_btn.state(["!disabled"]) else: self.exec_btn.state(["disabled"])
class Download(Frame): def __init__(self, master, **kwargs): super(Download, self).__init__(master, borderwidth=20, **kwargs) self.fs = None self.tree = None self.logfile = None # User informations self.info_tree = False self.start_time = None info = Frame(self, borderwidth=10) self.info_label = Label(info, wraplength=350, borderwidth=20, justify='center', font=('a', 10, 'bold')) self.info_indis = Label(info) self.info_fams = Label(info) self.info_sources = Label(info) self.info_notes = Label(info) self.time = Label(info) self.info_label.grid(row=0, column=0, columnspan=2) self.info_indis.grid(row=1, column=0) self.info_fams.grid(row=1, column=1) self.info_sources.grid(row=2, column=0) self.info_notes.grid(row=2, column=1) self.time.grid(row=3, column=0, columnspan=2) self.form = Frame(self) self.sign_in = SignIn(self.form) self.options = None self.title = Label(self, text=_('Sign In to FamilySearch'), font=('a', 12, 'bold')) buttons = Frame(self) self.btn_quit = Button(buttons, text=_('Quit'), command=Thread(target=self.quit).start) self.btn_valid = Button(buttons, text=_('Sign In'), command=self.command_in_thread(self.login)) self.title.pack() self.sign_in.pack() self.form.pack() self.btn_quit.pack(side='left', padx=(0, 40)) self.btn_valid.pack(side='right', padx=(40, 0)) info.pack() buttons.pack(side='bottom') self.pack() self.update_needed = False def info(self, text): self.info_label.config(text=text) def save(self): filename = filedialog.asksaveasfilename(title=_('Save as'), defaultextension='.ged', filetypes=(('GEDCOM', '.ged'), (_('All files'), '*.*'))) if not filename: return with open(filename, 'w', encoding='utf-8') as file: self.tree.print(file) def login(self): global _ username = self.sign_in.username.get() password = self.sign_in.password.get() if not (username and password): messagebox.showinfo(message=_('Please enter your FamilySearch username and password.')) return self.btn_valid.config(state='disabled') self.info(_('Login to FamilySearch...')) self.logfile = open('download.log', 'w', encoding='utf-8') self.fs = Session(self.sign_in.username.get(), self.sign_in.password.get(), verbose=True, logfile=self.logfile, timeout=1) if not self.fs.logged: messagebox.showinfo(_('Error'), message=_('The username or password was incorrect')) self.btn_valid.config(state='normal') self.info('') return self.tree = Tree(self.fs) _ = self.fs._ self.title.config(text=_('Options')) cache.delete('lang') cache.add('lang', self.fs.lang) self.options = Options(self.form, True) self.info('') self.sign_in.destroy() self.options.pack() self.master.change_lang() self.btn_valid.config(command=self.command_in_thread(self.download), state='normal', text=_('Download')) self.options.start_indis.add_indi(self.fs.get_userid()) self.update_needed = False def quit(self): self.update_needed = False if self.logfile: self.logfile.close() super(Download, self).quit() # prevent exception during download os._exit(1) def download(self): todo = [self.options.start_indis.indis[key] for key in sorted(self.options.start_indis.indis)] for fid in todo: if not re.match(r'[A-Z0-9]{4}-[A-Z0-9]{3}', fid): messagebox.showinfo(_('Error'), message=_('Invalid FamilySearch ID: ') + fid) return self.start_time = time.time() self.options.destroy() self.form.destroy() self.title.config(text='FamilySearch to GEDCOM') self.btn_valid.config(state='disabled') self.info(_('Download starting individuals...')) self.info_tree = True self.tree.add_indis(todo) todo = set(todo) done = set() for i in range(self.options.ancestors.get()): if not todo: break done |= todo self.info(_('Download ') + str(i + 1) + _('th generation of ancestors...')) todo = self.tree.add_parents(todo) - done todo = set(self.tree.indi.keys()) done = set() for i in range(self.options.descendants.get()): if not todo: break done |= todo self.info(_('Download ') + str(i + 1) + _('th generation of descendants...')) todo = self.tree.add_children(todo) - done if self.options.spouses.get(): self.info(_('Download spouses and marriage information...')) todo = set(self.tree.indi.keys()) self.tree.add_spouses(todo) ordi = self.options.ordinances.get() cont = self.options.contributors.get() async def download_stuff(loop): futures = set() for fid, indi in self.tree.indi.items(): futures.add(loop.run_in_executor(None, indi.get_notes)) if ordi: futures.add(loop.run_in_executor(None, self.tree.add_ordinances, fid)) if cont: futures.add(loop.run_in_executor(None, indi.get_contributors)) for fam in self.tree.fam.values(): futures.add(loop.run_in_executor(None, fam.get_notes)) if cont: futures.add(loop.run_in_executor(None, fam.get_contributors)) for future in futures: await future loop = asyncio.get_event_loop() self.info(_('Download notes') + (((',' if cont else _(' and')) + _(' ordinances')) if ordi else '') + (_(' and contributors') if cont else '') + '...') loop.run_until_complete(download_stuff(loop)) self.tree.reset_num() self.btn_valid.config(command=self.save, state='normal', text=_('Save')) self.info(text=_('Success ! Click below to save your GEDCOM file')) self.update_info_tree() self.update_needed = False def command_in_thread(self, func): def res(): self.update_needed = True Thread(target=self.update_gui).start() Thread(target=func).start() return res def update_info_tree(self): if self.info_tree and self.start_time and self.tree: self.info_indis.config(text=_('Individuals: %s') % len(self.tree.indi)) self.info_fams.config(text=_('Families: %s') % len(self.tree.fam)) self.info_sources.config(text=_('Sources: %s') % len(self.tree.sources)) self.info_notes.config(text=_('Notes: %s') % len(self.tree.notes)) t = round(time.time() - self.start_time) minutes = t // 60 seconds = t % 60 self.time.config(text=_('Elapsed time: %s:%s') % (minutes, '00%s'[len(str(seconds)):] % seconds)) def update_gui(self): while self.update_needed: self.update_info_tree() self.master.update() time.sleep(0.1)
class ParamsFrame(Notebook): ''' This class implements various operations with parameters like loading and saving from and to file, modifying parameters values. Attributes: parent (Tk object): parent of this widget. params (Parameters): Parameters object with values of all parameters. current_categories (list of str): list of current valid categories. input_categories (CategoriesCheckBox): frame for displaying input categories. output_categories (CategoriesCheckBox): frame for displaying output categories. params_from_file_lbl (Label): label for displaying file name if parameters were loaded from file. data_from_params_file(StringVar): StringVar object used for communication of this widget with DataFrame. Changing the value of data_from_params_file triggers changes in DataFrame (like clearing all data and loading data from file). str_var_for_input_output_boxes (ObserverStringVar): ObserverStringVar object used for storing input and output categories and for tracking changes in input and output categories. weight_tab (WeightFrame): widget used for displaying and editing weights. load_without_data (IntVar): IntVar object used for Checkbutton, if its value is 1, then parameters will be loaded from file without data, if its value is 0, then parameters will be loaded from file with data. options_frame (OptionsFrame): widget used for displaying and modifying some of the parameters. Args: parent (Tk object): parent of this widget. current_categories (list of str): list of current valid categories. data_from_params_file(StringVar): StringVar object used for communication of this widget with DataFrame. Changing the value of data_from_params_file triggers changes in DataFrame (like clearing all data and loading data from file). str_var_for_input_output_boxes (ObserverStringVar): ObserverStringVar object used for storing input and output categories and for tracking changes in input and output categories. weights_status_str (StringVar): StringVar object used for changing label of weights editor, for details see WeightFrame. ''' def __init__(self, parent, current_categories, data_from_params_file, str_var_for_input_output_boxes, weights_status_str, *args, **kw): Notebook.__init__(self, parent, *args, **kw) self.parent = parent self.params = Parameters() self.current_categories = current_categories self.input_categories_frame = None self.output_categories_frame = None self.params_from_file_lbl = None self.data_from_params_file = data_from_params_file self.str_var_for_input_output_boxes = str_var_for_input_output_boxes self.weight_tab = None self.load_without_data = IntVar() self.options_frame = None self.create_widgets(weights_status_str) def create_widgets(self, weights_status_str): ''' Creates all widgets. ''' self.enable_traversal() self._create_params_tab() self.weight_tab = WeightFrame(self, self.current_categories, self.params, weights_status_str) self.add(self.weight_tab, text='Weights editor') def change_weight_tab_name(self, new_name): ''' Changes name of weights editor tab. Args: new_name (str): new name for weights editor tab. ''' self.tab(1, text=new_name) def _create_params_tab(self): ''' Creates all widgets of the parameters tab. ''' frame_for_all_objects = VerticalScrolledFrame(self) frame_for_all_objects.columnconfigure(0, weight=1) frame_for_all_objects.rowconfigure(0, weight=1) params_tab = frame_for_all_objects.interior params_tab.columnconfigure(0, weight=1, pad=5) frame_for_save_btns = Frame(params_tab) frame_for_save_btns.columnconfigure(0, weight=1) frame_for_save_btns.columnconfigure(1, weight=1) load_btn = Button(frame_for_save_btns, text='Load parameters', command=self.load_file) load_btn.grid(row=0, column=0, sticky=W + N, pady=2) load_wo_data_box = Checkbutton(frame_for_save_btns, text='Load without data', variable=self.load_without_data) load_wo_data_box.grid(row=1, column=0, sticky=W + N, pady=2) save_btn = Button(frame_for_save_btns, text='Save parameters', command=self.on_save_params) save_btn.grid(row=0, column=1, sticky=E + N, pady=2) save_btn = Button(frame_for_save_btns, text='Save parameters as...', command=self.on_save_params_as) save_btn.grid(row=1, column=1, sticky=E + N, pady=2) frame_for_save_btns.grid(row=0, column=0, sticky=E + W, padx=XPAD_VALUE, pady=YPAD_VALUE) self.params_from_file_lbl = Label(params_tab, text=TEXT_FOR_PARAMS_LBL, anchor=W, justify=LEFT, wraplength=MAX_FILE_LBL_LENGTH) self.params_from_file_lbl.grid(row=1, column=0, columnspan=3, sticky=W + N, padx=XPAD_VALUE, pady=YPAD_VALUE) input_categories_list = CategoriesCheckBox(params_tab, 'Input categories:', True, self.params, 'INPUT_CATEGORIES') self.input_categories_frame = input_categories_list input_categories_list.grid(row=4, column=0, sticky=W + N + S + E, padx=XPAD_VALUE, pady=YPAD_VALUE, columnspan=2) output_categories_list = CategoriesCheckBox(params_tab, 'Output categories:', False, self.params, 'OUTPUT_CATEGORIES') self.output_categories_frame = output_categories_list output_categories_list.grid(row=5, column=0, sticky=W + N + S + E, padx=XPAD_VALUE, pady=YPAD_VALUE, columnspan=2) self.options_frame = OptionsFrame(params_tab, self.params, self.current_categories, self.input_categories_frame, self.output_categories_frame) self.options_frame.grid(row=6, column=0, columnspan=2, sticky=N + S + W + E, padx=XPAD_VALUE, pady=YPAD_VALUE) self.add(frame_for_all_objects, text='Parameters') def on_save_params(self): ''' Saves current parameter values to a file from where the\ parameters were loaded. This file name is displayed. If no file name is displayed (i.e. parameters were not previously loaded from file), then asksaveasfilename dialogue is called. ''' file_name = self.params_from_file_lbl.cget('text') if TEXT_FOR_PARAMS_LBL in file_name: file_name = file_name[len(TEXT_FOR_PARAMS_LBL):] if file_name: write_parameters_to_file(self.params, file_name) else: self.on_save_params_as() def on_save_params_as(self): ''' Calls asksaveasfilename dialogue and saves current values of parameters to the specified file. ''' file_name = self._get_file_name_to_save() if file_name: write_parameters_to_file(self.params, file_name) def _get_file_name_to_save(self): ''' Calls asksaveasfilename dialogue. This method is overridden in unit tests. Returns: (str): file name. ''' return asksaveasfilename(filetypes=[('Text files', '*.txt')], defaultextension='.txt') def load_file(self): ''' Loads parameters from file specified by the user. ''' file_name = self._get_filename_for_load() if file_name: self.str_var_for_input_output_boxes.input_categories.clear() self.str_var_for_input_output_boxes.output_categories.clear() # save previous params params_to_restore = dict() for param_name in CATEGORICAL_AND_DATA_FIELDS: params_to_restore[ param_name] = self.params.get_parameter_value(param_name) self.params.copy_all_params(parse_parameters_from_file(file_name)) if self.load_without_data.get() == 0: self.load_data_file_and_related_params(file_name, params_to_restore) else: self.data_from_params_file.set('') # restore previous parameters for param_name, value in params_to_restore.items(): self.params.update_parameter(param_name, value) self.options_frame.set_params_values() def _get_filename_for_load(self): ''' Calls askopenfilename dialogue. This method is overridden in unit tests. Returns: (str): file name. ''' file_types = [('Text files', '*.txt'), ('All files', '*.*')] file_name = askopenfilename(title='Choose a file', filetypes=file_types) return file_name def load_data_file_and_related_params(self, file_name, params_to_restore): ''' Loads data if possible and sets widgets to proper values depending on parameters. Args: file_name (str): file name of file with parameters. It is needed to display it on parameters frame. params_to_restore (dict of str to str): dictionary of previous values of parameters. They are used in order to restore previous values if loading of data from file fails. ''' data_file = self.params.get_parameter_value('DATA_FILE') norm_data_path = os.path.normpath(data_file) if os.path.isfile(norm_data_path): params_to_restore = dict() # I have to store this here, because when I clean all data # from data tab, it deletes these values from params for param_name in CATEGORICAL_AND_DATA_FIELDS: params_to_restore[ param_name] = self.params.get_parameter_value(param_name) # this line calls clear all from data_tab self.data_from_params_file.set(norm_data_path) self.params_from_file_lbl.config(text=TEXT_FOR_PARAMS_LBL + file_name) for param_name, value in params_to_restore.items(): self.params.update_parameter(param_name, value) self.add_categories( 'INPUT_CATEGORIES', self.input_categories_frame, self.str_var_for_input_output_boxes.input_categories) self.add_categories( 'OUTPUT_CATEGORIES', self.output_categories_frame, self.str_var_for_input_output_boxes.output_categories) self.str_var_for_input_output_boxes.set('notify') self.weight_tab.add_weights() else: self._show_warning(norm_data_path) for param_name, value in params_to_restore.items(): self.params.update_parameter(param_name, value) def _show_warning(self, norm_data_path): ''' Shows warning that data cannot be loaded from file. This method is overridden in unit tests. ''' showwarning( 'Warning', 'Cannot load data file: ' + norm_data_path + '. Parameters will be loaded without data.') def change_category_name(self, old_name, new_name): ''' Changes category name in parameters and all widgets to a new name. If new name is empty string, then some of the parameters might be lost (for example, weight restrictions will be lost). Args: old_name (str): old name of the category. new_name (str): new name of the category. ''' if old_name != new_name: self.input_categories_frame.change_category_name( old_name, new_name) self.output_categories_frame.change_category_name( old_name, new_name) self.weight_tab.add_weights() if self.options_frame.combobox_text_var.get() == old_name: self.options_frame.change_categorical_box() self.options_frame.set_categorical_box(new_name) def add_categories(self, name, frame, categories_container): ''' Adds input or output categories to a specified widget with categories from parameters. Args: name (str): name of the parameter where categories come from, possible values INPUT_CATEGORIES, OUTPUT_CATEGORIES. frame (CategoriesCheckBox): widget where categories will be added. categories_container (list of str): list of categories where categories from parameters will be added. ''' categories = self.params.get_set_of_parameters(name) for category in categories: # we add only categories that are # present in data file if category in self.current_categories: frame.add_category(category) categories_container.append(category) else: self.params.remove_category_from_params(name, category) def clear_all(self): ''' Clears all parameters and corresponding widgets. ''' self.input_categories_frame.remove_all_categories() self.output_categories_frame.remove_all_categories() self.options_frame.combobox_text_var.set('') self.weight_tab.remove_all_weights() self.params.clear_all_categorical_and_data_fields() self.params_from_file_lbl.config(text='') self.str_var_for_input_output_boxes.input_categories.clear() self.str_var_for_input_output_boxes.output_categories.clear()
buttons = {} butlist = [] for i in range(7*7): b = tk.Button(root, text=sdx['butval'][i]) buttons[b] = i b.bind("<Button-1>", butfunction) c1 = 21 + ((i % 7) * 27) c2 = 113 + ((math.trunc(i / 7)) * 16) b.place(x=c1,y=c2) b.config(height=1, width=2, borderwidth=0, bg='white', font=("Helvetica", 7)) butlist.append(b) butlist[sdx['tdateoffset']].config(bg='skyblue') label = Label(root, background='white') label.place(relx=0.5,rely=0.005,anchor='n') label.config(text=str(sdx['juldate']),font=("Helvetica", 74)) month_up_icon = tk.PhotoImage(file='./juldate22/assets/bluedot15.png') month_up_button = ttk.Button( root, image=month_up_icon, command=month_up_clicked ) month_up_button.place(x=190,y=0) month_down_icon = tk.PhotoImage(file='./juldate22/assets/bluedot15.png') month_down_button = ttk.Button( root, image=month_down_icon, command=month_down_clicked )
class MainDialog(Frame): def __init__(self, root): super().__init__() self.assetFile = ('./DefaultAssetList.xlsx') self.root = root self.initUI() def initUI(self): #Task menu menubar = Menu(self.master) self.master.config(menu=menubar) fileMenu = Menu(menubar) fileMenu.add_command(label="Load Asset File", command=self.onOpen) fileMenu.add_command(label="Close", command=sys.exit) menubar.add_cascade(label="File", menu=fileMenu) #Note: Each time a .pack is called, it creates a new frame self.master.title("MobileView Assistant") self.root.rowconfigure(1, pad=10) self.root.rowconfigure(2, pad=10) self.root.rowconfigure(3, pad=10) self.root.rowconfigure(4, pad=10) self.root.rowconfigure(5, pad=10) self.root.rowconfigure(6, pad=10) self.root.rowconfigure(7, pad=10) self.root.rowconfigure(8, pad=10) self.root.rowconfigure(9, pad=10) self.root.rowconfigure(10, pad=10) self.root.rowconfigure(11, pad=10) self.root.columnconfigure(1, pad=5) self.root.columnconfigure(2, pad=5) self.root.columnconfigure(3, pad=5) self.root.columnconfigure(4, pad=5) #Username area lbl1 = Label(self.root, text="MV Username:"******"RSQ Username:"******"MV Password:"******"*") MVPassword.grid(row=2, column=2) lbl10 = Label(self.root, text="RSQ Password:"******"*") RSQPassword.grid(row=2, column=4) #File area lbl3 = Label(self.root, text="Asset File:", width=10) lbl3.grid(row=3, column=1) assetButton = Button(self.root, text="Browse", command=self.onOpen) assetButton.grid(row=3, column=2, sticky="w") self.lbl4 = Label(self.root, text=os.path.basename(self.assetFile)) self.lbl4.grid(row=4, column=2, columnspan=2, sticky="w") #Trial Type Selector lbl7 = Label(self.root, text="Trial Type:", width=10) lbl7.grid(row=5, column=1) options = [ "All Assets", "PM Month: January", "PM Month: February", "PM Month: March", "PM Month: April", "PM Month: May", "PM Month: June", "PM Month: July", "PM Month: August", "PM Month: September", "PM Month: October", "PM Month: November", "PM Month: December" ] trial_type = StringVar() trial_type.set(options[0]) trial_selector = OptionMenu(self.root, trial_type, *options) trial_selector.grid(row=5, column=2, columnspan=2, sticky="WE") #Admin Access Checker self.admin_access = IntVar(value=1) Checkbutton(self.root, text="I have access to Mobile View Admin.", variable=self.admin_access).grid(row=6, column=1, columnspan=2, sticky=W) #Active PMs only Checker self.cross_checker = IntVar(value=1) Checkbutton(self.root, text="Print only the active PMs.", variable=self.cross_checker).grid(row=7, column=1, columnspan=2, sticky=W) #Run a test only Checker self.test_case = IntVar(value=0) Checkbutton(self.root, text="Run a test trial only.", variable=self.test_case).grid(row=6, column=3, columnspan=2, sticky=W) #Email Results Checker self.email_results = IntVar(value=0) Checkbutton(self.root, text="Email results to ResultsMailingList.txt.", variable=self.email_results).grid(row=7, column=3, columnspan=2, sticky=W) #Status Indicator lbl5 = Label(self.root, text="Status:", width=10) lbl5.grid(row=10, column=1) self.lbl6 = Label(self.root, text="Awaiting Inputs...", width=50) self.lbl6.grid(row=10, column=2, columnspan=5) #Ok and close button okButton = Button( self.root, text="Run", command=lambda: self.mainProgram( MVUsername.get(), MVPassword.get(), RSQUsername.get(), RSQPassword.get(), self.assetFile, trial_type.get(), self.admin_access.get(), self.test_case.get(), self.email_results.get(), self.cross_checker.get())) okButton.grid(row=11, column=2, sticky="WE") closeButton = Button(self.root, text="Close", command=sys.exit) #use quit to close window closeButton.grid(row=11, column=3, sticky="E") #Copyright Line lbl8 = Label(self.root, text="© Ryan Mooney Industries", width=10) lbl8.grid(row=12, column=1, columnspan=3, sticky="WE") self.centerWindow() def mainProgram(self, MVUsername, MVPassword, RSQUsername, RSQPassword, assetfile, trial_type, admin_access, test_case, email_results, cross_checker): #Checks credentials before continuing credentials_correct = checkCredentials(MVUsername, MVPassword, RSQUsername, RSQPassword, cross_checker, self.root, self.lbl6) if credentials_correct == "NO": return () #Compiles a dictionary with each asset and its descriptors self.lbl6.config(text='Finding Assets...') self.root.update() #Determines how to find asset locations if test_case == 1: trial_type = 'TEST' assetList, floor_counter, floor_list = get_asset_locations_test( MVUsername, MVPassword, assetListCreator(assetfile, trial_type), self.root, self.lbl6) elif admin_access == 1: assetList, floor_counter, floor_list = get_asset_locations_admin( MVUsername, MVPassword, assetListCreator(assetfile, trial_type), self.root, self.lbl6) else: assetList, floor_counter, floor_list = get_asset_locations_nonadmin( MVUsername, MVPassword, assetListCreator(assetfile, trial_type), self.root, self.lbl6) #Saves each new asset data point to database with unique 'trial' number self.lbl6.config(text='Saving Data...') self.root.update() connection = connect() assetList, trial = assign_trial_number(assetList, connection, trial_type, test_case) save_to_db(assetList, self.root, self.lbl6, connection) connection.close() #If only active PMs are wanted, we cross check them with an RSQ list and return only the assets with active PMs if cross_checker == 1: self.lbl6.config(text='Cross checking for active PMs...') self.root.update() activeAssets = crossCheckAssets(assetList, RSQUsername, RSQPassword, self.root, self.lbl6) trial_type = trial_type + ' Active PMs Only' else: activeAssets = 'None' #Creates and Exports Data to Excel self.lbl6.config(text='Exporting to Excel...') self.root.update() file = exportToExcel(assetList, trial, floor_counter, floor_list, trial_type, activeAssets) #Sends results to email addresses if requested if email_results == 1: self.lbl6.config(text='Sending Emails...') self.root.update() email_file = './ResultsMailingList.txt' send_results(file, email_file) self.lbl6.config(text='Completed!') self.root.update() os.startfile(file) #Emails results, if possible def centerWindow(self): w = 475 h = 325 sw = self.master.winfo_screenwidth() sh = self.master.winfo_screenheight() x = (sw - w) / 2 y = (sh - h) / 2 self.master.geometry('%dx%d+%d+%d' % (w, h, x, y)) def onOpen(self): filename = filedialog.askopenfilename() self.lbl4.config(text=os.path.basename(filename)) self.assetFile = filename def readFile(self, filename): with open(filename, "rb") as f: text = f.read() return text def run(self): print('I am running')
class ResourcePathFrame(Frame): def __init__(self, parent, configuration): Frame.__init__(self, parent) self.configuration = configuration self.test_path_in = None self.test_path_in_res = configuration.test_path_in self.test_path_expected = None self.test_path_expected_res = configuration.test_path_expected self.results_path = None self.results_path_res = configuration.results_path self.logging_path = None self.logging_path_res = configuration.logging_path self.init_view() def init_view(self): self.test_path_in = Label(self, text=FileUtils.get_filename_from_path( self.configuration.test_path_in)) self.test_path_in.grid(row=0, column=1) Button(self, text="Browse...", command=self.browse_test_path_in) \ .grid(row=0, column=0) self.test_path_expected = Label( self, text=FileUtils.get_filename_from_path( self.configuration.test_path_expected)) self.test_path_expected.grid(row=1, column=1) Button(self, text="Browse...", command=self.browse_test_path_expected) \ .grid(row=1, column=0) self.results_path = Label(self, text=FileUtils.get_filename_from_path( self.configuration.results_path)) self.results_path.grid(row=2, column=1) Button(self, text="Browse...", command=self.browse_results_path) \ .grid(row=2, column=0) self.logging_path = Label(self, text=FileUtils.get_filename_from_path( self.configuration.logging_path)) self.logging_path.grid(row=3, column=1) Button(self, text="Browse...", command=self.browse_logging_path) \ .grid(row=3, column=0) def browse_test_path_in(self): self.test_path_in_res = filedialog.askdirectory() self.test_path_in.config(text=FileUtils.get_filename_from_path( self.test_path_in_res.split('/')[-1])) def browse_test_path_expected(self): self.test_path_expected_res = filedialog.askdirectory() self.test_path_expected.config(text=FileUtils.get_filename_from_path( self.test_path_expected_res.split('/')[-1])) def browse_results_path(self): self.results_path_res = filedialog.askdirectory() self.results_path.config(text=FileUtils.get_filename_from_path( self.results_path_res.split('/')[-1])) def browse_logging_path(self): self.logging_path_res = filedialog.askopenfilename() self.logging_path.config( text=FileUtils.get_filename_from_path(self.logging_path_res)) def get_values(self): return self.test_path_in_res, \ self.test_path_expected_res,\ self.results_path_res,\ self.logging_path_res
class BIDSSearchFrame(Frame): def __init__(self, master, parent=None, *args, **kwargs): self.master = master self.parent = parent super(BIDSSearchFrame, self).__init__(self.master, *args, **kwargs) # create some inital variables self.obj_var = OptionsVar( options=['project', 'subject', 'session', 'scan']) self.condition_var = OptionsVar( options=['<', '<=', '=', '!=', '!!=', '>=', '>']) self.results = None self._create_widgets() # the associated file self._file = None #region public methods def set_text(self, text): self.info_label.config(text=text) #region private methods def _create_widgets(self): self.info_label = Label(self, text='Search') self.info_label.grid(column=0, row=0, sticky='nw') Label(self, text='Search for a...').grid(column=0, row=1, sticky='nw') self.search_table = WidgetTable( self, headings=None, pattern=[{ 'var': self.obj_var, 'configs': { 'state': 'readonly' } }, { 'text': 'with' }, StringVar, { 'var': self.condition_var, 'configs': { 'state': 'readonly' } }, StringVar], widgets_pattern=[Combobox, Label, Entry, Combobox, Entry], data_array=[{ 'var': self.obj_var, 'configs': { 'state': 'readonly' } }, { 'text': 'with' }, StringVar(), { 'var': self.condition_var, 'configs': { 'state': 'readonly' } }, StringVar()], style={'nodividers': True}) self.search_table.grid(column=0, row=2, columnspan=2, sticky='nsew') self.search_button = Button(self, text='Search', command=self._search) self.search_button.grid(column=0, row=3, sticky='e') # results section Label(self, text='Results:').grid(column=0, row=4, sticky='nw') frame = Frame(self) frame.grid_rowconfigure(0, weight=1) frame.grid_columnconfigure(0, weight=1) xscrollbar = Scrollbar(frame, orient=HORIZONTAL) xscrollbar.grid(row=1, column=0, sticky='ew') yscrollbar = Scrollbar(frame) yscrollbar.grid(row=0, column=1, sticky='ns') self.results_frame = Text(frame, relief=FLAT, undo=False, takefocus=0, bg=OSCONST.TEXT_BG, wrap=NONE, xscrollcommand=xscrollbar.set, yscrollcommand=yscrollbar.set, state=DISABLED) self.results_frame.grid(row=0, column=0, sticky='nsew') self.hyperlink = HyperlinkManager(self.results_frame) xscrollbar.config(command=self.results_frame.xview) yscrollbar.config(command=self.results_frame.yview) frame.grid(column=0, row=5, columnspan=2, sticky='nsew') self.result_count_label = Label(self, text="Total results: 0") self.result_count_label.grid(column=0, row=6, sticky='w') export_button = Button(self, text='Export', command=self._export_results) export_button.grid(column=0, row=7, sticky='e') help_button = Button(self, text='Help', command=self._open_help) help_button.grid(column=1, row=7, sticky='e') self.grid_columnconfigure(0, weight=1) self.grid_rowconfigure(2, weight=1) self.grid_rowconfigure(5, weight=1) def _export_results(self): if len(self.results) != 0: # ask where to copy the data to dst = filedialog.askdirectory(title="Select BIDS folder") if dst != '': SendFilesWindow(self, self.results, dst, opt_verify=True) else: messagebox.showerror( 'No Results', 'No results to export. Please enter a set of ' 'valid search parameters to export data.') def _open_help(self): open_hyperlink(HELP_LINK) def _search(self): query = self.search_table.get() self.results = None try: for q in query: if self.results is None: self.results = self.file.query(q[0], q[2], q[3], str_to_obj(q[4])) else: self.results = self.results.query(q[0], q[2], q[3], str_to_obj(q[4])) except ValueError: messagebox.showerror( 'Invalid search', 'One or more search parameters are invalid. ' 'Please ensure your search criteria is ' 'correct.') self.results = [] str_results = list(get_bidsobj_info(x) for x in self.results) self.results_frame.config(state=NORMAL) # Clear all the current text. self.results_frame.delete(1.0, END) # Then add all the new results. for i, result in enumerate(str_results): self.results_frame.insert( END, result + '\n', self.hyperlink.add( lambda obj=self.results[i]: self._select_obj(obj))) # Set the frame to not be writable any more. if len(self.results) == 0: self.results_frame.insert(END, 'None') self.results_frame.config(state=DISABLED) self.result_count_label.config( text="Total results: {0}".format(len(self.results))) def _select_obj(self, obj): """Highlight the selected object in the treeview.""" # find the selected object's sid if isinstance(obj, Scan): # for scan objects we want to go to the actual raw object fpath = obj.raw_file else: fpath = obj.path obj_sid = self.parent.file_treeview.sid_from_filepath(fpath) # then show it self.parent.file_treeview.see(obj_sid) self.parent.file_treeview.focus(item=obj_sid) self.parent.file_treeview.selection_set((obj_sid, )) #region properties @property def file(self): return self._file @file.setter def file(self, other): """ Set the file property to whatever the new file is. When this happens the update command will be called which will redraw the channel info list """ if other != self._file: self._file = other
class Application(Frame): def __init__(self, parent): super().__init__(parent) self.Version = "YEDDA-V1.0 Annotator" self.OS = platform.system().lower() self.fileName = "" self.file_encoding = 'utf-8' self.debug = False self.history = deque(maxlen=20) self.pressCommand = [ KeyDef('a', "Artificial"), KeyDef('b', "Event"), KeyDef('c', "Fin-Concept"), KeyDef('d', "Location"), KeyDef('e', "Organization"), KeyDef('f', "Person"), KeyDef('g', "Sector"), KeyDef('h', "Other") ] for key, color in zip(self.pressCommand, all_colors()): key.color = color # default GUI display parameter self.textRow = max(len(self.pressCommand), 20) self.textColumn = 5 self.configFile = "configs/default.config" self.entity_regex = r'\[\@.*?\#.*?\*\](?!\#)' self.recommendRe = r'\[\$.*?\#.*?\*\](?!\#)' self.goldAndrecomRe = r'\[[\@\$)].*?\#.*?\*\](?!\#)' self.textFontStyle = "Times" self.initUI() def initUI(self): self.master.title(self.Version) self.pack(fill=BOTH, expand=True) for i in range(0, self.textColumn): self.columnconfigure(i, weight=2) # self.columnconfigure(0, weight=2) self.columnconfigure(self.textColumn + 2, weight=1) self.columnconfigure(self.textColumn + 4, weight=1) for i in range(0, 16): self.rowconfigure(i, weight=1) self.filename_lbl = Label(self, text="File: no file is opened") self.filename_lbl.grid(sticky=W, pady=4, padx=5) self.text = Editor(self, self.entity_regex, self.recommendRe) self.text.grid(row=1, column=0, columnspan=self.textColumn, rowspan=self.textRow, padx=12, sticky=NSEW) btn = Button(self, text="Open", command=self.onOpen) btn.grid(row=1, column=self.textColumn + 1) btn = Button(self, text="ReMap", command=self.renewPressCommand) btn.grid(row=2, column=self.textColumn + 1, pady=4) btn = Button(self, text="NewMap", command=self.savenewPressCommand) btn.grid(row=3, column=self.textColumn + 1, pady=4) btn = Button(self, text="Export", command=self.generateSequenceFile) btn.grid(row=4, column=self.textColumn + 1, pady=4) self.use_recommend = BooleanVar(self, True) check = Checkbutton(self, text='Recommend', command=self.toggle_use_recommend, variable=self.use_recommend) check.grid(row=5, column=self.textColumn + 1, sticky=W, pady=4) show_tags_var = BooleanVar(self, True) check = Checkbutton( self, text='Show Tags', variable=show_tags_var, command=lambda: self.text.show_annotation_tag(show_tags_var.get())) check.grid(row=6, column=self.textColumn + 1, sticky=W) self.use_colorful_var = BooleanVar(self, False) check = Checkbutton(self, text='Colorful', variable=self.use_colorful_var, command=self.toggle_use_colorful) check.grid(row=7, column=self.textColumn + 1, sticky=W) self.cursor_index_label = Label(self, text="Ln 1, Col 0") self.cursor_index_label.grid(row=self.textRow + 1, sticky=NSEW, pady=4, padx=4) cmd_var = StringVar() cmd_var.trace_add('write', lambda _, _1, _2: self.preview_cmd_range()) self.entry = Entry(self, validate='focus', vcmd=self.preview_cmd_range, textvariable=cmd_var) self.entry.grid(row=self.textRow + 1, column=1, columnspan=self.textColumn - 2, sticky=NSEW, pady=4, padx=8) self.entry.bind('<FocusOut>', self.clear_preview_mark) self.entry.bind('<Return>', self.execute_command) btn = Button(self, text="Enter", command=lambda: self.execute_command(None)) btn.grid(row=self.textRow + 1, column=self.textColumn - 1) all_keys = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" for press_key in all_keys: self.text.bind(press_key, self.alphanum_key_pressed, add='') if self.OS != "windows": self.text.bind(f'<Control-Key-"{press_key}">', self.keepCurrent) self.text.bind(f'<Command-Key-"{press_key}">', self.keepCurrent) self.text.bind('<Control-Key-z>', self.backToHistory) self.text.bind('<Double-Button-1>', self.doubleLeftClick) self.text.bind('<ButtonRelease-1>', self.show_cursor_pos) self.text.bind('<KeyRelease>', self.show_cursor_pos) self.keymap_frame = KeyMapFrame(self, self.pressCommand) self.keymap_frame.grid(row=1, column=self.textColumn + 2, rowspan=self.keymap_frame.rows, columnspan=2, padx=6, pady=6, sticky=NW) Label(self, text="KeyMap Templates:").grid(row=8, column=self.textColumn + 1) self.configListBox = Combobox(self, values=getConfigList(), state='readonly') self.configListBox.grid(row=8, column=self.textColumn + 2, columnspan=2) # select current config file self.configListBox.set(self.configFile.split(os.sep)[-1]) self.configListBox.bind('<<ComboboxSelected>>', self.on_select_configfile) def show_cursor_pos(self, _): cursor_index = self.text.index(INSERT) row, col = cursor_index.split('.') self.cursor_index_label.config(text=f"Ln {row}, Col {col}") # TODO: select entity by double left click def doubleLeftClick(self, _): if self.debug: print("Action Track: doubleLeftClick") pass # cursor_index = self.text.index(INSERT) # start_index = ("%s - %sc" % (cursor_index, 5)) # end_index = ("%s + %sc" % (cursor_index, 5)) # self.text.tag_add('SEL', '1.0',"end-1c") def toggle_use_recommend(self): if not self.use_recommend.get(): content = self.text.get_text() content = removeRecommendContent(content, self.recommendRe) self.writeFile(self.fileName, content, '1.0') def toggle_use_colorful(self): if self.use_colorful_var.get(): self.text.set_colors([(d.name, d.color) for d in self.pressCommand]) else: self.text.set_colors(None) self.text.update_view() def onOpen(self): filename = filedialog.askopenfilename( filetypes=[('all files', '.*'), ('text files', '.txt'), ('ann files', '.ann')]) if filename != '': self.text.delete("1.0", END) text = self.readFile(filename) self.text.insert(END, text) self.filename_lbl.config(text="File: " + filename) self.autoLoadNewFile(self.fileName, "1.0") self.text.mark_set(INSERT, "1.0") self.show_cursor_pos(None) def readFile(self, filename): f = open(filename) try: text = f.read() self.file_encoding = f.encoding except UnicodeDecodeError: f = open(filename, encoding='utf-8') text = f.read() self.fileName = filename return text def setFont(self, value): _family = self.textFontStyle _size = value _weight = "bold" _underline = 0 fnt = font.Font(family=_family, size=_size, weight=_weight, underline=_underline) Text(self, font=fnt) def setCursorLabel(self, cursor_index): row, col = cursor_index.split('.') self.cursor_index_label.config(text=f"Ln {row}, Col {col}") def clear_preview_mark(self, _): self.text.tag_delete('cmd-preview') def preview_cmd_range(self): preview_tag = 'cmd-preview' cmd = self.entry.get().strip() self.text.tag_delete(preview_tag) self.text.tag_configure(preview_tag, background='light salmon') match = re.match(r'^(-?[0-9]+).*', cmd) if match: count = int(match.group(1)) else: count = 1 if count > 0: self.text.tag_add(preview_tag, INSERT, f'{INSERT}+{count}c') else: self.text.tag_add(preview_tag, f'{INSERT}-{abs(count)}c', INSERT) return True def execute_command(self, _): self.pushToHistory() content = self.entry.get() self.clearCommand() self.execute_entry_command(content.strip()) return content def alphanum_key_pressed(self, event): press_key = event.char self.pushToHistory() self.clearCommand() self.execute_cursor_command(press_key.lower()) return 'break' def backToHistory(self, _): if self.debug: print("Action Track: backToHistory") if len(self.history) > 0: content, cursor = self.history.pop() self.writeFile(self.fileName, content, cursor) else: print("History is empty!") def keepCurrent(self, _): if self.debug: print("Action Track: keepCurrent") print("keep current, insert:", INSERT) print("before:", self.text.index(INSERT)) self.text.insert(INSERT, 'p') print("after:", self.text.index(INSERT)) def clearCommand(self): if self.debug: print("Action Track: clearCommand") self.entry.delete(0, 'end') def execute_cursor_command(self, command): print("Command:" + command) found, (start, end) = self.text.current_entity() selected = self.text.get_selection() if not found and not selected: print(f'{command} outside entity, no selection, do nothing') return # selected whole entity, cursor just outside it selected_whole = selected is not None and \ (re.match(self.entity_regex, selected) or re.match(self.recommendRe, selected)) # cursor outside existing entity & has selection if not found and selected is not None and not selected_whole: if self.get_cmd_by_key(command) is None: print(f'{command} key not bound, outside entity, do nothing') return cursor_index = self.text.index(SEL_LAST) entity_content, cursor_index = self.replaceString( selected, selected, command, cursor_index) above_half = self.text.get('1.0', SEL_FIRST) + entity_content below_half = self.text.get(SEL_LAST, "end-1c") content = self.addRecommendContent(above_half, below_half, self.use_recommend.get()) self.writeFile(self.fileName, content, cursor_index) # Cursor inside existing entity, no matter has or not has selection. # Or Cursor outside existing entity (just on the edge), with the whole entity selected else: if selected_whole: start, end = self.text.index(SEL_FIRST), self.text.index( SEL_LAST) covered_string = self.text.get(start, end) old_entity, old_label = covered_string.strip('[@$*]').rsplit( '#', 1) if command == "q": print('q: remove entity label') new_cursor = f'{end}-{5 + len(old_label)}c' entity_content = old_entity elif command == 'y': print("y: confirm recommend label") entity_content = f'[@{old_entity}#{old_label}*]' new_cursor = end elif len(old_entity) > 0 and self.get_cmd_by_key( command) is not None: print(f'{command}: change entity type') cmd = self.get_cmd_by_key(command) entity_content = f'[@{old_entity}#{cmd.name}*]' delta = len(cmd.name) - len(old_label) new_cursor = end + (f'+{delta}c' if delta >= 0 else f'{delta}c') else: print(f'{command}: key not bound, do nothing') return above_half = self.text.get('1.0', start) + entity_content below_half = self.text.get(end, 'end-1c') content = self.addRecommendContent(above_half, below_half, self.use_recommend.get()) self.writeFile(self.fileName, content, new_cursor) def execute_entry_command(self, command): print(f"EntryCommand: {command}") if command == '': # move to next line row, _ = self.text.index(INSERT).split('.') self.text.mark_set(INSERT, f'{int(row) + 1}.0') self.show_cursor_pos(None) elif command.isdigit(): self.text.mark_set(INSERT, f'{INSERT}+{command}c') self.show_cursor_pos(None) self.preview_cmd_range() elif len(command) >= 2 and command[0] == '-' and command[1:].isdigit(): self.text.mark_set(INSERT, f'{INSERT}{command}c') self.show_cursor_pos(None) self.preview_cmd_range() else: def split_commands(string): commands = [] num = '' for c in string: if c.isdigit(): num += c else: commands.append((int(num), c)) num = '' return commands for select_num, cmd in split_commands(command): assert select_num > 0 sel_start = self.text.index(INSERT) sel_end = self.text.index(f'{INSERT}+{select_num}c') selected = self.text.get(sel_start, sel_end) if self.get_cmd_by_key(cmd) is not None: above_half = self.text.get('1.0', sel_start) below_half = self.text.get(sel_start, "end-1c") below_half, new_cursor = self.replaceString( below_half, selected, cmd, sel_end) content = self.addRecommendContent( above_half, below_half, self.use_recommend.get()) self.writeFile(self.fileName, content, new_cursor) def replaceString(self, content, string, replaceType, cursor_index): keydef = self.get_cmd_by_key(replaceType) if keydef is not None: new_string = "[@" + string + "#" + keydef.name + "*]" row, col = cursor_index.split('.') newcursor_index = f"{row}.{int(col) + len(keydef.name) + 5}" content = content.replace(string, new_string, 1) return content, newcursor_index else: print("Invalid command!") print("cursor index: ", self.text.index(INSERT)) return content, cursor_index def writeFile(self, fileName, content, newcursor_index): print("writeFile") if len(fileName) > 0: if ".ann" in fileName: new_name = fileName ann_file = open(new_name, 'w', encoding=self.file_encoding) ann_file.write(content) ann_file.close() else: new_name = fileName + '.ann' ann_file = open(new_name, 'w', encoding=self.file_encoding) ann_file.write(content) ann_file.close() self.autoLoadNewFile(new_name, newcursor_index) else: print("Don't write to empty file!") def addRecommendContent(self, train_data, decode_data, recommendMode): if not recommendMode: content = train_data + decode_data else: if self.debug: print( "Action Track: addRecommendContent, start Recommend entity" ) content = maximum_matching(train_data, decode_data) return content def autoLoadNewFile(self, fileName, newcursor_index): if self.debug: print("Action Track: autoLoadNewFile") if len(fileName) > 0: self.text.delete("1.0", END) text = self.readFile(fileName) self.text.insert("end-1c", text) self.filename_lbl.config(text="File: " + fileName) self.text.mark_set(INSERT, newcursor_index) self.text.see(newcursor_index) self.show_cursor_pos(None) self.text.update_view() def pushToHistory(self): self.history.append((self.text.get_text(), self.text.index(INSERT))) # update shortcut map, directly in current configfile def renewPressCommand(self): if self.debug: print("Action Track: renewPressCommand") self.pressCommand = self.keymap_frame.read_keymap() with open(self.configFile, 'w') as fp: fp.write(str(self.pressCommand)) self.keymap_frame.update_keymap(self.pressCommand) messagebox.showinfo( "Remap Notification", "Shortcut map has been updated!\n\n" + "Configure file has been saved in File:" + self.configFile) # save as new shortcut map def savenewPressCommand(self): if self.debug: print("Action Track: savenewPressCommand") self.pressCommand = self.keymap_frame.read_keymap() # prompt to ask configFile name self.configFile = filedialog.asksaveasfilename( initialdir="./configs/", title="Save New Config", filetypes=(("YEDDA configs", "*.config"), ("all files", "*.*"))) # change to relative path following self.init() self.configFile = os.path.relpath(self.configFile) # make sure ending with ".config" if not self.configFile.endswith(".config"): self.configFile += ".config" with open(self.configFile, 'w') as fp: fp.write(str(self.pressCommand)) self.keymap_frame.update_keymap(self.pressCommand) messagebox.showinfo( "Save New Map Notification", "Shortcut map has been saved and updated!\n\n" + "Configure file has been saved in File:" + self.configFile) def on_select_configfile(self, event=None): if event and self.debug: print("Change shortcut map to: ", event.widget.get()) self.configFile = os.path.join("configs", event.widget.get()) self.keymap_frame.update_keymap(self.pressCommand) def generateSequenceFile(self): if (".ann" not in self.fileName) and (".txt" not in self.fileName): out_error = "Export only works on filename ended in .ann or .txt!\nPlease rename file." print(out_error) messagebox.showerror("Export error!", out_error) return -1 dlg = QueryExport(self, self.fileName, self.text.get_text()[:100]) if not dlg.confirmed: print("Operation canceled") return fileLines = open(self.fileName, 'r', encoding=self.file_encoding).readlines() lineNum = len(fileLines) new_filename = self.fileName.split( '.ann')[0] + '.' + dlg.tag_scheme().lower() seqFile = open(new_filename, 'w', encoding=self.file_encoding) for line in fileLines: if len(line) <= 2: seqFile.write('\n') continue else: if not dlg.keep_recommended(): line = removeRecommendContent(line, self.recommendRe) pattern = self.entity_regex else: pattern = self.goldAndrecomRe wordTagPairs = getWordTagPairs(line, dlg.segmented(), dlg.tag_scheme(), dlg.only_NP(), pattern) for wordTag in wordTagPairs: seqFile.write(wordTag) # use null line to separate sentences seqFile.write('\n') seqFile.close() print("Exported file into sequence style in file: ", new_filename) print("Line number:", lineNum) showMessage = "Exported file successfully!\n\n" showMessage += "Tag scheme: " + dlg.tag_scheme() + "\n\n" showMessage += "Keep Recom: " + str(dlg.keep_recommended()) + "\n\n" showMessage += "Text Segmented: " + str(dlg.segmented()) + "\n\n" showMessage += "Line Number: " + str(lineNum) + "\n\n" showMessage += "Saved to File: " + new_filename messagebox.showinfo("Export Message", showMessage) def get_cmd_by_key(self, key): return next((item for item in self.pressCommand if item.key == key), None) def get_cmd_by_name(self, name): return next((item for item in self.pressCommand if item.name == name), None)
class DialogPluginManager(Toplevel): def __init__(self, mainWin, modulesWithNewerFileDates): super(DialogPluginManager, self).__init__(mainWin.parent) self.ENABLE = _("Enable") self.DISABLE = _("Disable") self.parent = mainWin.parent self.cntlr = mainWin # copy plugins for temporary display self.pluginConfig = PluginManager.pluginConfig self.pluginConfigChanged = False self.uiClassMethodsChanged = False self.modelClassesChanged = False self.customTransformsChanged = False self.disclosureSystemTypesChanged = False self.hostSystemFeaturesChanged = False self.modulesWithNewerFileDates = modulesWithNewerFileDates parentGeometry = re.match("(\d+)x(\d+)[+]?([-]?\d+)[+]?([-]?\d+)", self.parent.geometry()) dialogX = int(parentGeometry.group(3)) dialogY = int(parentGeometry.group(4)) self.title(_("Plug-in Manager")) frame = Frame(self) # left button frame buttonFrame = Frame(frame, width=40) buttonFrame.columnconfigure(0, weight=1) addLabel = Label(buttonFrame, text=_("Find plug-in modules:"), wraplength=60, justify="center") addSelectLocalButton = Button(buttonFrame, text=_("Select"), command=self.selectLocally) ToolTip( addSelectLocalButton, text=_( "Select python module files from the local plugin directory."), wraplength=240) addBrowseLocalButton = Button(buttonFrame, text=_("Browse"), command=self.browseLocally) ToolTip( addBrowseLocalButton, text= _("File chooser allows browsing and selecting python module files to add (or reload) plug-ins, from the local file system." ), wraplength=240) addWebButton = Button(buttonFrame, text=_("On Web"), command=self.findOnWeb) ToolTip( addWebButton, text= _("Dialog to enter URL full path to load (or reload) plug-ins, from the web or local file system." ), wraplength=240) addLabel.grid(row=0, column=0, pady=4) addSelectLocalButton.grid(row=1, column=0, pady=4) addBrowseLocalButton.grid(row=2, column=0, pady=4) addWebButton.grid(row=3, column=0, pady=4) buttonFrame.grid(row=0, column=0, rowspan=3, sticky=(N, S, W), padx=3, pady=3) # right tree frame (plugins already known to arelle) modulesFrame = Frame(frame, width=720) vScrollbar = Scrollbar(modulesFrame, orient=VERTICAL) hScrollbar = Scrollbar(modulesFrame, orient=HORIZONTAL) self.modulesView = Treeview(modulesFrame, xscrollcommand=hScrollbar.set, yscrollcommand=vScrollbar.set, height=7) self.modulesView.grid(row=0, column=0, sticky=(N, S, E, W)) self.modulesView.bind('<<TreeviewSelect>>', self.moduleSelect) hScrollbar["command"] = self.modulesView.xview hScrollbar.grid(row=1, column=0, sticky=(E, W)) vScrollbar["command"] = self.modulesView.yview vScrollbar.grid(row=0, column=1, sticky=(N, S)) modulesFrame.columnconfigure(0, weight=1) modulesFrame.rowconfigure(0, weight=1) modulesFrame.grid(row=0, column=1, columnspan=4, sticky=(N, S, E, W), padx=3, pady=3) self.modulesView.focus_set() self.modulesView.column("#0", width=120, anchor="w") self.modulesView.heading("#0", text=_("Name")) self.modulesView["columns"] = ("author", "ver", "status", "date", "update", "descr", "license") self.modulesView.column("author", width=100, anchor="w", stretch=False) self.modulesView.heading("author", text=_("Author")) self.modulesView.column("ver", width=60, anchor="w", stretch=False) self.modulesView.heading("ver", text=_("Version")) self.modulesView.column("status", width=50, anchor="w", stretch=False) self.modulesView.heading("status", text=_("Status")) self.modulesView.column("date", width=70, anchor="w", stretch=False) self.modulesView.heading("date", text=_("File Date")) self.modulesView.column("update", width=50, anchor="w", stretch=False) self.modulesView.heading("update", text=_("Update")) self.modulesView.column("descr", width=200, anchor="w", stretch=False) self.modulesView.heading("descr", text=_("Description")) self.modulesView.column("license", width=70, anchor="w", stretch=False) self.modulesView.heading("license", text=_("License")) classesFrame = Frame(frame) vScrollbar = Scrollbar(classesFrame, orient=VERTICAL) hScrollbar = Scrollbar(classesFrame, orient=HORIZONTAL) self.classesView = Treeview(classesFrame, xscrollcommand=hScrollbar.set, yscrollcommand=vScrollbar.set, height=5) self.classesView.grid(row=0, column=0, sticky=(N, S, E, W)) hScrollbar["command"] = self.classesView.xview hScrollbar.grid(row=1, column=0, sticky=(E, W)) vScrollbar["command"] = self.classesView.yview vScrollbar.grid(row=0, column=1, sticky=(N, S)) classesFrame.columnconfigure(0, weight=1) classesFrame.rowconfigure(0, weight=1) classesFrame.grid(row=1, column=1, columnspan=4, sticky=(N, S, E, W), padx=3, pady=3) self.classesView.focus_set() self.classesView.column("#0", width=200, anchor="w") self.classesView.heading("#0", text=_("Class")) self.classesView["columns"] = ("modules", ) self.classesView.column("modules", width=500, anchor="w", stretch=False) self.classesView.heading("modules", text=_("Modules")) # bottom frame module info details moduleInfoFrame = Frame(frame, width=700) moduleInfoFrame.columnconfigure(1, weight=1) self.moduleNameLabel = Label(moduleInfoFrame, wraplength=600, justify="left", font=font.Font(family='Helvetica', size=12, weight='bold')) self.moduleNameLabel.grid(row=0, column=0, columnspan=4, sticky=W) self.moduleAuthorHdr = Label(moduleInfoFrame, text=_("author:"), state=DISABLED) self.moduleAuthorHdr.grid(row=1, column=0, sticky=W) self.moduleAuthorLabel = Label(moduleInfoFrame, wraplength=600, justify="left") self.moduleAuthorLabel.grid(row=1, column=1, columnspan=3, sticky=W) self.moduleDescrHdr = Label(moduleInfoFrame, text=_("description:"), state=DISABLED) self.moduleDescrHdr.grid(row=2, column=0, sticky=W) self.moduleDescrLabel = Label(moduleInfoFrame, wraplength=600, justify="left") self.moduleDescrLabel.grid(row=2, column=1, columnspan=3, sticky=W) self.moduleClassesHdr = Label(moduleInfoFrame, text=_("classes:"), state=DISABLED) self.moduleClassesHdr.grid(row=3, column=0, sticky=W) self.moduleClassesLabel = Label(moduleInfoFrame, wraplength=600, justify="left") self.moduleClassesLabel.grid(row=3, column=1, columnspan=3, sticky=W) ToolTip(self.moduleClassesLabel, text=_("List of classes that this plug-in handles."), wraplength=240) self.moduleVersionHdr = Label(moduleInfoFrame, text=_("version:"), state=DISABLED) self.moduleVersionHdr.grid(row=4, column=0, sticky=W) self.moduleVersionLabel = Label(moduleInfoFrame, wraplength=600, justify="left") self.moduleVersionLabel.grid(row=4, column=1, columnspan=3, sticky=W) ToolTip(self.moduleVersionLabel, text=_("Version of plug-in module."), wraplength=240) self.moduleUrlHdr = Label(moduleInfoFrame, text=_("URL:"), state=DISABLED) self.moduleUrlHdr.grid(row=5, column=0, sticky=W) self.moduleUrlLabel = Label(moduleInfoFrame, wraplength=600, justify="left") self.moduleUrlLabel.grid(row=5, column=1, columnspan=3, sticky=W) ToolTip( self.moduleUrlLabel, text=_( "URL of plug-in module (local file path or web loaded file)."), wraplength=240) self.moduleDateHdr = Label(moduleInfoFrame, text=_("date:"), state=DISABLED) self.moduleDateHdr.grid(row=6, column=0, sticky=W) self.moduleDateLabel = Label(moduleInfoFrame, wraplength=600, justify="left") self.moduleDateLabel.grid(row=6, column=1, columnspan=3, sticky=W) ToolTip( self.moduleDateLabel, text= _("Date of currently loaded module file (with parenthetical node when an update is available)." ), wraplength=240) self.moduleLicenseHdr = Label(moduleInfoFrame, text=_("license:"), state=DISABLED) self.moduleLicenseHdr.grid(row=7, column=0, sticky=W) self.moduleLicenseLabel = Label(moduleInfoFrame, wraplength=600, justify="left") self.moduleLicenseLabel.grid(row=7, column=1, columnspan=3, sticky=W) self.moduleImportsHdr = Label(moduleInfoFrame, text=_("imports:"), state=DISABLED) self.moduleImportsHdr.grid(row=8, column=0, sticky=W) self.moduleImportsLabel = Label(moduleInfoFrame, wraplength=600, justify="left") self.moduleImportsLabel.grid(row=8, column=1, columnspan=3, sticky=W) self.moduleEnableButton = Button(moduleInfoFrame, text=self.ENABLE, state=DISABLED, command=self.moduleEnable) ToolTip(self.moduleEnableButton, text=_("Enable/disable plug in."), wraplength=240) self.moduleEnableButton.grid(row=9, column=1, sticky=E) self.moduleReloadButton = Button(moduleInfoFrame, text=_("Reload"), state=DISABLED, command=self.moduleReload) ToolTip(self.moduleReloadButton, text=_("Reload/update plug in."), wraplength=240) self.moduleReloadButton.grid(row=9, column=2, sticky=E) self.moduleRemoveButton = Button(moduleInfoFrame, text=_("Remove"), state=DISABLED, command=self.moduleRemove) ToolTip( self.moduleRemoveButton, text= _("Remove plug in from plug in table (does not erase the plug in's file)." ), wraplength=240) self.moduleRemoveButton.grid(row=9, column=3, sticky=E) moduleInfoFrame.grid(row=2, column=0, columnspan=5, sticky=(N, S, E, W), padx=3, pady=3) moduleInfoFrame.config(borderwidth=4, relief="groove") okButton = Button(frame, text=_("Close"), command=self.ok) ToolTip(okButton, text=_("Accept and changes (if any) and close dialog."), wraplength=240) cancelButton = Button(frame, text=_("Cancel"), command=self.close) ToolTip(cancelButton, text=_("Cancel changes (if any) and close dialog."), wraplength=240) okButton.grid(row=3, column=3, sticky=(S, E), pady=3) cancelButton.grid(row=3, column=4, sticky=(S, E), pady=3, padx=3) enableDisableFrame = Frame(frame) enableDisableFrame.grid(row=3, column=1, sticky=(S, W), pady=3) enableAllButton = Button(enableDisableFrame, text=_("Enable All"), command=self.enableAll) ToolTip(enableAllButton, text=_("Enable all plug ins."), wraplength=240) disableAllButton = Button(enableDisableFrame, text=_("Disable All"), command=self.disableAll) ToolTip(disableAllButton, text=_("Disable all plug ins."), wraplength=240) enableAllButton.grid(row=1, column=1) disableAllButton.grid(row=1, column=2) self.loadTreeViews() self.geometry("+{0}+{1}".format(dialogX + 50, dialogY + 100)) frame.grid(row=0, column=0, sticky=(N, S, E, W)) frame.columnconfigure(0, weight=0) frame.columnconfigure(1, weight=1) frame.rowconfigure(0, weight=1) window = self.winfo_toplevel() window.columnconfigure(0, weight=1) window.rowconfigure(0, weight=1) self.bind("<Return>", self.ok) self.bind("<Escape>", self.close) self.protocol("WM_DELETE_WINDOW", self.close) self.grab_set() self.wait_window(self) def loadTreeViews(self): self.selectedModule = None # clear previous treeview entries for previousNode in self.modulesView.get_children(""): self.modulesView.delete(previousNode) def loadSubtree(parentNode, moduleItems): for moduleItem in sorted(moduleItems, key=lambda item: item[0]): moduleInfo = moduleItem[1] if parentNode or not moduleInfo.get("isImported"): nodeName = moduleItem[0] if parentNode: nodeName = parentNode + GROUPSEP + nodeName name = moduleInfo.get("name", nodeName) node = self.modulesView.insert(parentNode, "end", nodeName, text=name) self.modulesView.set(node, "author", moduleInfo.get("author")) self.modulesView.set(node, "ver", moduleInfo.get("version")) self.modulesView.set(node, "status", moduleInfo.get("status")) self.modulesView.set(node, "date", moduleInfo.get("fileDate")) if name in self.modulesWithNewerFileDates: self.modulesView.set(node, "update", _("available")) self.modulesView.set(node, "descr", moduleInfo.get("description")) self.modulesView.set(node, "license", moduleInfo.get("license")) if moduleInfo.get("imports"): loadSubtree( node, [(importModuleInfo["name"], importModuleInfo) for importModuleInfo in moduleInfo["imports"]]) loadSubtree("", self.pluginConfig.get("modules", {}).items()) # clear previous treeview entries for previousNode in self.classesView.get_children(""): self.classesView.delete(previousNode) for i, classItem in enumerate( sorted(self.pluginConfig.get("classes", {}).items())): className, moduleList = classItem node = self.classesView.insert("", "end", className, text=className) self.classesView.set(node, "modules", ', '.join(moduleList)) self.moduleSelect() # clear out prior selection def ok(self, event=None): # check for orphaned classes (for which there is no longer a corresponding module) _moduleNames = self.pluginConfig.get("modules", {}).keys() _orphanedClassNames = set() for className, moduleList in self.pluginConfig.get("classes", {}).items(): for _moduleName in moduleList.copy(): if _moduleName not in _moduleNames: # it's orphaned moduleList.remove(_moduleName) self.pluginConfigChanged = True if not moduleList: # now orphaned _orphanedClassNames.add(className) self.pluginConfigChanged = True for _orphanedClassName in _orphanedClassNames: del self.pluginConfig["classes"][_orphanedClassName] if self.pluginConfigChanged: PluginManager.pluginConfig = self.pluginConfig PluginManager.pluginConfigChanged = True PluginManager.reset() # force reloading of modules if self.uiClassMethodsChanged or self.modelClassesChanged or self.customTransformsChanged or self.disclosureSystemTypesChanged or self.hostSystemFeaturesChanged: # may require reloading UI affectedItems = "" if self.uiClassMethodsChanged: affectedItems += _("menus of the user interface") if self.modelClassesChanged: if affectedItems: affectedItems += _(" and ") affectedItems += _("model objects of the processor") if self.customTransformsChanged: if affectedItems: affectedItems += _(" and ") affectedItems += _("custom transforms") if self.disclosureSystemTypesChanged: if affectedItems: affectedItems += _(" and ") affectedItems += _("disclosure system types") if self.hostSystemFeaturesChanged: if affectedItems: affectedItems += _(" and ") affectedItems += _("host system features") if messagebox.askyesno( _("User interface plug-in change"), _("A change in plug-in class methods may have affected {0}. " "Please restart Arelle to due to these changes. \n\n" "Should Arelle restart itself now " "(if there are any unsaved changes they would be lost!)?" ).format(affectedItems), parent=self): self.cntlr.uiThreadQueue.put((self.cntlr.quit, [None, True])) self.close() def close(self, event=None): self.parent.focus_set() self.destroy() def moduleSelect(self, *args): node = (self.modulesView.selection() or (None, ))[0] if node: node = node.rpartition(GROUPSEP)[ 2] # drop leading path names for module name moduleInfo = self.pluginConfig.get("modules", {}).get(node) if moduleInfo: self.selectedModule = node name = moduleInfo["name"] self.moduleNameLabel.config(text=name) self.moduleAuthorHdr.config(state=ACTIVE) self.moduleAuthorLabel.config(text=moduleInfo.get("author")) self.moduleDescrHdr.config(state=ACTIVE) self.moduleDescrLabel.config(text=moduleInfo.get("description")) self.moduleClassesHdr.config(state=ACTIVE) self.moduleClassesLabel.config( text=', '.join(moduleInfo["classMethods"])) self.moduleVersionHdr.config(state=ACTIVE) self.moduleVersionLabel.config(text=moduleInfo.get("version")) self.moduleUrlHdr.config(state=ACTIVE) self.moduleUrlLabel.config(text=moduleInfo["moduleURL"]) self.moduleDateHdr.config(state=ACTIVE) self.moduleDateLabel.config( text=moduleInfo["fileDate"] + " " + (_("(an update is available)") if name in self.modulesWithNewerFileDates else "")) self.moduleLicenseHdr.config(state=ACTIVE) self.moduleLicenseLabel.config(text=moduleInfo.get("license")) if moduleInfo.get("imports"): self.moduleImportsHdr.config(state=ACTIVE) _text = ", ".join(mi["name"] for mi in moduleInfo["imports"][:3]) if len(moduleInfo["imports"]) >= 3: _text += ", ..." self.moduleImportsLabel.config(text=_text) _buttonState = DISABLED if moduleInfo.get("isImported") else ACTIVE self.moduleEnableButton.config(state=_buttonState, text={ "enabled": self.DISABLE, "disabled": self.ENABLE }[moduleInfo["status"]]) self.moduleReloadButton.config(state=_buttonState) self.moduleRemoveButton.config(state=_buttonState) else: self.selectedModule = None self.moduleNameLabel.config(text="") self.moduleAuthorHdr.config(state=DISABLED) self.moduleAuthorLabel.config(text="") self.moduleDescrHdr.config(state=DISABLED) self.moduleDescrLabel.config(text="") self.moduleClassesHdr.config(state=DISABLED) self.moduleClassesLabel.config(text="") self.moduleVersionHdr.config(state=DISABLED) self.moduleVersionLabel.config(text="") self.moduleUrlHdr.config(state=DISABLED) self.moduleUrlLabel.config(text="") self.moduleDateHdr.config(state=DISABLED) self.moduleDateLabel.config(text="") self.moduleLicenseHdr.config(state=DISABLED) self.moduleLicenseLabel.config(text="") self.moduleImportsHdr.config(state=DISABLED) self.moduleImportsLabel.config(text="") self.moduleEnableButton.config(state=DISABLED, text=self.ENABLE) self.moduleReloadButton.config(state=DISABLED) self.moduleRemoveButton.config(state=DISABLED) def selectLocally(self): choices = [] # list of tuple of (file name, description) def sortOrder(key): return { "EdgarRenderer": "1", "validate": "2", "xbrlDB": "3" }.get(key, "4") + key.lower() def selectChoices(dir, indent=""): dirHasEntries = False for f in sorted(os.listdir(dir), key=sortOrder): if f not in (".", "..", "__pycache__", "__init__.py"): fPath = os.path.join(dir, f) fPkgInit = os.path.join(fPath, "__init__.py") dirInsertPoint = len(choices) moduleInfo = None if ((os.path.isdir(fPath) and os.path.exists(fPkgInit)) or ((os.path.isfile(fPath) and f.endswith(".py")))): moduleInfo = PluginManager.moduleModuleInfo(fPath) if moduleInfo: choices.append(( indent + f, "name: {}\ndescription: {}\nversion: {}\nlicense: {}" .format(moduleInfo["name"], moduleInfo.get("description"), moduleInfo.get("version"), moduleInfo.get("license")), fPath, moduleInfo["name"], moduleInfo.get("version"), moduleInfo.get("description"), moduleInfo.get("license"))) dirHasEntries = True if os.path.isdir(fPath) and f not in ("DQC_US_Rules", ): if selectChoices(fPath, indent=indent + " ") and not moduleInfo: choices.insert(dirInsertPoint, (indent + f, None, None, None, None, None, None)) return dirHasEntries selectChoices(self.cntlr.pluginDir) selectedPath = DialogOpenArchive.selectPlugin(self, choices) if selectedPath: moduleInfo = PluginManager.moduleModuleInfo( selectedPath[len(self.cntlr.pluginDir) + 1:]) self.loadFoundModuleInfo(moduleInfo, selectedPath) def browseLocally(self): initialdir = self.cntlr.pluginDir # default plugin directory if not self.cntlr.isMac: # can't navigate within app easily, always start in default directory initialdir = self.cntlr.config.setdefault("pluginOpenDir", initialdir) filename = self.cntlr.uiFileDialog( "open", parent=self, title=_("Choose plug-in module file"), initialdir=initialdir, filetypes=[(_("Python files"), "*.py")], defaultextension=".py") if filename: # check if a package is selected (any file in a directory containing an __init__.py #if (os.path.basename(filename) == "__init__.py" and os.path.isdir(os.path.dirname(filename)) and # os.path.isfile(filename)): # filename = os.path.dirname(filename) # refer to the package instead self.cntlr.config["pluginOpenDir"] = os.path.dirname(filename) moduleInfo = PluginManager.moduleModuleInfo(filename) self.loadFoundModuleInfo(moduleInfo, filename) def findOnWeb(self): url = DialogURL.askURL(self) if url: # url is the in-cache or local file moduleInfo = PluginManager.moduleModuleInfo(url) self.cntlr.showStatus("") # clear web loading status self.loadFoundModuleInfo(moduleInfo, url) def loadFoundModuleInfo(self, moduleInfo, url): if moduleInfo and moduleInfo.get("name"): self.addPluginConfigModuleInfo(moduleInfo) self.loadTreeViews() else: messagebox.showwarning( _("Module is not itself a plug-in or in a directory with package __init__.py plug-in. " ), _("File does not itself contain a python program with an appropriate __pluginInfo__ declaration: \n\n{0}" ).format(url), parent=self) def checkIfImported(self, moduleInfo): if moduleInfo.get("isImported"): messagebox.showwarning( _("Plug-in is imported by a parent plug-in. "), _("Plug-in has a parent, please request operation on the parent: \n\n{0}" ).format(moduleInfo.get("name")), parent=self) return True return False def checkClassMethodsChanged(self, moduleInfo): for classMethod in moduleInfo["classMethods"]: if classMethod.startswith("CntlrWinMain.Menu"): self.uiClassMethodsChanged = True # may require reloading UI elif classMethod == "ModelObjectFactory.ElementSubstitutionClasses": self.modelClassesChanged = True # model object factor classes changed elif classMethod == "ModelManager.LoadCustomTransforms": self.customTransformsChanged = True elif classMethod == "DisclosureSystem.Types": self.disclosureSystemTypesChanged = True # disclosure system types changed elif classMethod.startswith("Proxy."): self.hostSystemFeaturesChanged = True # system features (e.g., proxy) changed def removePluginConfigModuleInfo(self, name): moduleInfo = self.pluginConfig["modules"].get(name) if moduleInfo: if self.checkIfImported(moduleInfo): return def _removePluginConfigModuleInfo(moduleInfo): _name = moduleInfo.get("name") if _name: self.checkClassMethodsChanged(moduleInfo) for classMethod in moduleInfo["classMethods"]: classMethods = self.pluginConfig["classes"].get( classMethod) if classMethods and _name in classMethods: classMethods.remove(_name) if not classMethods: # list has become unused del self.pluginConfig["classes"][ classMethod] # remove class for importModuleInfo in moduleInfo.get( "imports", EMPTYLIST): _removePluginConfigModuleInfo(importModuleInfo) self.pluginConfig["modules"].pop(_name, None) _removePluginConfigModuleInfo(moduleInfo) if not self.pluginConfig["modules"] and self.pluginConfig[ "classes"]: self.pluginConfig["classes"].clear() # clean orphan classes self.pluginConfigChanged = True def addPluginConfigModuleInfo(self, moduleInfo): if self.checkIfImported(moduleInfo): return name = moduleInfo.get("name") self.removePluginConfigModuleInfo( name) # remove any prior entry for this module def _addPlugin(moduleInfo): _name = moduleInfo.get("name") if _name: self.modulesWithNewerFileDates.discard( _name) # no longer has an update available self.pluginConfig["modules"][_name] = moduleInfo # add classes for classMethod in moduleInfo["classMethods"]: classMethods = self.pluginConfig["classes"].setdefault( classMethod, []) if name not in classMethods: classMethods.append(_name) self.checkClassMethodsChanged(moduleInfo) for importModuleInfo in moduleInfo.get("imports", EMPTYLIST): _addPlugin(importModuleInfo) _addPlugin(moduleInfo) self.pluginConfigChanged = True def moduleEnable(self): if self.selectedModule in self.pluginConfig["modules"]: moduleInfo = self.pluginConfig["modules"][self.selectedModule] if self.checkIfImported(moduleInfo): return def _moduleEnable(moduleInfo): if self.moduleEnableButton['text'] == self.ENABLE: moduleInfo["status"] = "enabled" elif self.moduleEnableButton['text'] == self.DISABLE: moduleInfo["status"] = "disabled" self.checkClassMethodsChanged(moduleInfo) for importModuleInfo in moduleInfo.get("imports", EMPTYLIST): _moduleEnable( importModuleInfo) # set status on nested moduleInfo if importModuleInfo['name'] in self.pluginConfig[ "modules"]: # set status on top level moduleInfo _moduleEnable(self.pluginConfig["modules"][ importModuleInfo['name']]) _moduleEnable(moduleInfo) if self.moduleEnableButton['text'] == self.ENABLE: self.moduleEnableButton['text'] = self.DISABLE elif self.moduleEnableButton['text'] == self.DISABLE: self.moduleEnableButton['text'] = self.ENABLE self.pluginConfigChanged = True self.loadTreeViews() def moduleReload(self): if self.selectedModule in self.pluginConfig["modules"]: url = self.pluginConfig["modules"][self.selectedModule].get( "moduleURL") if url: moduleInfo = PluginManager.moduleModuleInfo(url, reload=True) if moduleInfo: if self.checkIfImported(moduleInfo): return self.addPluginConfigModuleInfo(moduleInfo) self.loadTreeViews() self.cntlr.showStatus(_("{0} reloaded").format( moduleInfo["name"]), clearAfter=5000) else: messagebox.showwarning( _("Module error"), _("File or module cannot be reloaded: \n\n{0}").format( url), parent=self) def moduleRemove(self): if self.selectedModule in self.pluginConfig["modules"]: self.removePluginConfigModuleInfo(self.selectedModule) self.pluginConfigChanged = True self.loadTreeViews() def enableAll(self): self.enableDisableAll(True) def disableAll(self): self.enableDisableAll(False) def enableDisableAll(self, doEnable): for module in self.pluginConfig["modules"]: moduleInfo = self.pluginConfig["modules"][module] if not moduleInfo.get("isImported"): def _enableDisableAll(moduleInfo): if doEnable: moduleInfo["status"] = "enabled" else: moduleInfo["status"] = "disabled" for importModuleInfo in moduleInfo.get( "imports", EMPTYLIST): _enableDisableAll(importModuleInfo) _enableDisableAll(moduleInfo) if doEnable: self.moduleEnableButton['text'] = self.DISABLE else: self.moduleEnableButton['text'] = self.ENABLE self.pluginConfigChanged = True self.loadTreeViews()
class TtkScale(Scale): def __init__(self, parent, length=0, from_=0, to=255, orient='horizontal', variable=0, digits=0, tickinterval=None, sliderlength=32, command=None, style=None, showvalue=True, resolution=1): self.from_ = from_ self.to = to self.variable = variable self.length = length self.command = command self.parent = parent self.orient = orient super().__init__(parent, length=length, from_=from_, to=to, orient=orient, variable=variable, command=command, style=style) self.digits = digits self.tickinterval = tickinterval self.showvalue = showvalue self.resolution = resolution self.sliderlength = sliderlength # = 32 theme_sl = { 'alt': 9, 'clam': 30, 'classic': 30, 'default': 30, 'lime': 9, 'winnative': 9 } theme_bw = { 'alt': 0, 'clam': 1, 'classic': 2, 'default': 1, 'lime': 6, 'winnative': 0 } # set trough borderwidth st = Style(self) theme_used = st.theme_use() if theme_used in ('alt', 'clam', 'classic', 'default', 'lime', 'winnative'): self.bw_val = bw_val = theme_bw[theme_used] self.sliderlength = sliderlength = theme_sl[theme_used] else: self.bw_val = bw_val = 1 if showvalue: self.configure(command=self.display_value) def_font = font.nametofont('TkDefaultFont') # if from_ more than to swap values if from_ < to: pass else: from_, to = to, from_ data = np.arange(from_, (to + 1 if tickinterval >= 1 else to + tickinterval), tickinterval) self.data = data = np.round(data, 1) range_vals = tuple(data) len_rvs = len(range_vals) if self.orient == 'horizontal': vals_size = [def_font.measure(str(i)) for i in range_vals] data_size = sum(vals_size) space_size = len_rvs * def_font.measure('0') else: lspace = def_font.metrics('linespace') data_size = len_rvs * lspace space_size = len_rvs * 3 sizes = data_size + space_size min_len = (sizes if sizes % 50 == 0 else sizes + 50 - sizes % 50) self.len_val = len_val = min_len if length < min_len else length self.configure(length=len_val) self.rel_min = rel_min = (sliderlength // 2 + bw_val) / len_val self.rel_max = rel_max = 1 - (sliderlength // 2 + bw_val) / len_val if range_vals[-1] == to: pass else: max_rv = range_vals[-1] self.mult_l = ((max_rv - from_) * rel_max / (to - from_)) self.bind("<Button-1>", self.resolve) self.build(from_, to, rel_min, rel_max, range_vals, len_rvs) def build(self, from_, to, rel_min, rel_max, range_vals, len_rvs): if self.orient == 'horizontal': for i, rv in enumerate(range_vals): item = Label(self.parent, text=rv) item.place( in_=self, bordermode='outside', relx=(rel_min + i / (len_rvs - 1) * ((rel_max if range_vals[-1] == to else self.mult_l) - rel_min)), rely=1, anchor='n') else: for i, rv in enumerate(range_vals): item = Label(self.parent, text=rv) item.place( in_=self, bordermode='outside', rely=(rel_min + i / (len_rvs - 1) * ((rel_max if range_vals[-1] == to else self.mult_l) - rel_min)), relx=1, anchor='w') if self.showvalue: self.disp_lab = Label(self.parent, text=self.get()) rel_l = self.convert_to_rel(float(self.get())) if self.orient == 'horizontal': self.disp_lab.place(in_=self, bordermode='outside', relx=rel_l, rely=0, anchor='s') else: self.disp_lab.place(in_=self, bordermode='outside', rely=rel_l, relx=0, anchor='e') def convert_to_rel(self, curr_val): return ((curr_val - self.from_) * (self.rel_max - self.rel_min) / (self.to - self.from_) + self.rel_min) def convert_to_act(self, curr_val): l_max = self.rel_max * self.len_val l_min = self.rel_min * self.len_val return ((curr_val - self.from_) * (l_max - l_min) / (self.to - self.from_) + l_min) def display_value(self, value): # position (in pixel) of the center of the slider rel_l = self.convert_to_rel(float(value)) self.disp_lab.config(text=value) # text="" if self.orient == 'horizontal': self.disp_lab.place_configure(relx=rel_l) else: self.disp_lab.place_configure(rely=rel_l) digits = self.digits self.disp_lab.configure(text=f'{float(value):.{digits}f}') # if your python is not 3.6 or above use the following 2 lines # instead of the line above #my_precision = '{:.{}f}'.format #self.disp_lab.configure(text=my_precision(float(value), digits)) def resolve(self, evt): resolution = self.resolution if resolution < 1 or self.tickinterval < 1: pass else: value = self.get() curr_l = self.convert_to_act(value) if self.orient == 'horizontal': if evt.x < curr_l - self.sliderlength / 2: self.set(value - resolution + 1) elif evt.x > curr_l + self.sliderlength / 2: self.set(value + resolution - 1) else: if evt.y < curr_l - self.sliderlength / 2: self.set(value - resolution + 1) elif evt.y > curr_l + self.sliderlength / 2: self.set(value + resolution - 1)
class MatsFrame(Frame): """ The frame that interacts with the test sequence in order to display the \ test results as the test is executing. :param parent: the tk parent frame :param sequence: the instance of `TestSequence` to monitor :param vertical: if `True`, will stack tests vertically; \ otherwise, horizontally :param start_btn: if `True`, will populate a start button; \ otherwise, will not :param loglevel: the logging level, for instance 'logging.INFO' """ def __init__(self, parent, sequence: TestSequence, vertical=False, start_btn=True, loglevel=logging.INFO): self._logger = logging.getLogger(self.__class__.__name__) self._logger.setLevel(loglevel) self._parent = parent super().__init__(self._parent) self._sequence = sequence arrow = '\u2b9e' if not vertical else '\u2b9f' row = 0 col = 0 if start_btn: Button(self, text='Start', command=sequence.start)\ .grid(row=row, column=col, sticky='news') if not vertical: col += 1 if not vertical else 0 row += 1 if vertical else 0 Label(self, text=arrow, justify='center', anchor='center')\ .grid(row=row, column=col, sticky='news') col += 1 if not vertical else 0 row += 1 if vertical else 0 self._test_status_frames = [] for test in self._sequence.tests: self._test_status_frames.append( _TestLabel(self, test, vertical=vertical)) for i, tl in enumerate(self._test_status_frames): col += 1 if not vertical else 0 row += 1 if vertical else 0 tl.grid(row=row, column=col, sticky='news') if not vertical: col += 1 if not vertical else 0 row += 1 if vertical else 0 Label(self, text=arrow, justify='center', anchor='center')\ .grid(row=row, column=col, sticky='news') col += 1 if not vertical else 0 row += 1 if vertical else 0 self._complete_label = Label(self, text='-', anchor='center', justify='center') self._complete_label.grid(row=row, column=col, sticky='news') self._complete_label.config(relief=_relief, padding=_label_padding) self._update() def _update(self): if self._sequence.in_progress: self._complete_label.config(text='in progress', background=_light_yellow) elif self._sequence.is_aborted: self._complete_label.config(text='aborted', background=_light_red) elif self._sequence.is_passing: self._complete_label.config(text='pass', background=_light_green) else: self._complete_label.config(text='fail', background=_light_red) self.after(100, self._update)
class Report(Frame): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.root = self.winfo_toplevel() self.root.title(" ".join((APPNAME, VERSION, "| Report"))) self.root.resizable(0, 0) self.items = None headers = ('Page', 'Rank', 'PageRank Value', 'Incoming') self.t = Scale(self, from_=0, to=1, label='n-th iteration', bd=1, width=7, orient='horizontal', command=self.__set_t) self.t.pack(fill='x') self.label = Label(self, anchor='e') self.label.pack(fill='x') self.tree = Treeview(self, columns=headers, show="headings", height=REPORT_HEIGHT) self.tree.column(0, anchor='center', width=55) self.tree.column(1, anchor='center', width=55) self.tree.column(2, width=175) self.tree.column(3, anchor='center', width=55) self.scroll = Scrollbar(self, command=self.tree.yview) self.scroll.pack(side='right', fill='y') self.tree.config(yscrollcommand=self.scroll.set) for col in headers: self.tree.heading(col, text=col.title()) self.root.master.focus_force() self.root.bind('<Key>', self.__keys) def __keys(self, event): if event.char == 'i': self.t.set(self.t.get() - 1) elif event.char == 'I': self.t.set(0) elif event.char == 'o': self.t.set(self.t.get() + 1) elif event.char == 'O': self.t.set(self.pagerank[1]) def __set_t(self, t=None): self.render(self.pagerank, self.edge_counts, self.d, self.e, t=int(t)) def render(self, pagerank, edge_counts, d, e, t=None): self.d, self.e = d, e self.edge_counts = edge_counts self.pagerank = pagerank if t is not None: pr = pagerank[0][t] else: self.t.config(command=None) self.t.config(to=self.pagerank[1]) self.t.set(self.pagerank[1]) self.t.config(command=self.__set_t) pr = pagerank[0][-1] label_text = '# of ranks:{0:>3} # of iterations:{1:>3}'.format( len(set(pr.values())), self.pagerank[1]) self.label.config(text=label_text) in_map = {k: 0 for k in pr.keys()} # incoming edges by nodes for (tail, head), n in edge_counts.items(): if tail is not head: in_map[head] += n get_rank = lambda k: sorted(pr.values())[::-1].index(pr[k]) + 1 data = tuple( (k, get_rank(k), pr[k], in_map[k]) for k in sorted(pr.keys())) if self.items: self.tree.delete(*self.items) self.items = [ self.tree.insert('', 'end', values=line) for line in data ] self.tree.pack(side='left', fill='y') #self.root.master.focus_force() def destroy(self): super().destroy() self.root.master.r_win = False self.root.master.windowsmenu.entryconfig(0, label='[ ] Report window') self.root.destroy()
class DialogPackageManager(Toplevel): def __init__(self, mainWin, packageNamesWithNewerFileDates): super(DialogPackageManager, self).__init__(mainWin.parent) self.ENABLE = _("Enable") self.DISABLE = _("Disable") self.parent = mainWin.parent self.cntlr = mainWin # copy plugins for temporary display self.packagesConfig = PackageManager.packagesConfig self.packagesConfigChanged = False self.packageNamesWithNewerFileDates = packageNamesWithNewerFileDates parentGeometry = re.match("(\d+)x(\d+)[+]?([-]?\d+)[+]?([-]?\d+)", self.parent.geometry()) dialogX = int(parentGeometry.group(3)) dialogY = int(parentGeometry.group(4)) self.title(_("Taxonomy Packages Manager")) frame = Frame(self) # left button frame buttonFrame = Frame(frame, width=40) buttonFrame.columnconfigure(0, weight=1) addLabel = Label(buttonFrame, text=_("Find taxonomy packages:"), wraplength=64, justify="center") addLocalButton = Button(buttonFrame, text=_("Locally"), command=self.findLocally) ToolTip(addLocalButton, text=_("File chooser allows selecting taxonomy packages to add (or reload), from the local file system. " "Select either a taxonomy package zip file, or a taxonomy manifest (.taxonomyPackage.xml) within an unzipped taxonomy package. "), wraplength=240) addWebButton = Button(buttonFrame, text=_("On Web"), command=self.findOnWeb) ToolTip(addWebButton, text=_("Dialog to enter URL full path to load (or reload) package, from the web or local file system. " "URL may be either a taxonomy package zip file, or a taxonomy manifest (.taxonomyPackage.xml) within an unzipped taxonomy package. "), wraplength=240) manifestNameButton = Button(buttonFrame, text=_("Manifest"), command=self.manifestName) ToolTip(manifestNameButton, text=_("Provide non-standard archive manifest file name pattern (e.g., *taxonomyPackage.xml). " "Uses unix file name pattern matching. " "Multiple manifest files are supported in archive (such as oasis catalogs). " "(Replaces search for either .taxonomyPackage.xml or catalog.xml). "), wraplength=240) self.manifestNamePattern = "" addLabel.grid(row=0, column=0, pady=4) addLocalButton.grid(row=1, column=0, pady=4) addWebButton.grid(row=2, column=0, pady=4) manifestNameButton.grid(row=3, column=0, pady=4) buttonFrame.grid(row=0, column=0, rowspan=3, sticky=(N, S, W), padx=3, pady=3) # right tree frame (packages already known to arelle) packagesFrame = Frame(frame, width=700) vScrollbar = Scrollbar(packagesFrame, orient=VERTICAL) hScrollbar = Scrollbar(packagesFrame, orient=HORIZONTAL) self.packagesView = Treeview(packagesFrame, xscrollcommand=hScrollbar.set, yscrollcommand=vScrollbar.set, height=7) self.packagesView.grid(row=0, column=0, sticky=(N, S, E, W)) self.packagesView.bind('<<TreeviewSelect>>', self.packageSelect) hScrollbar["command"] = self.packagesView.xview hScrollbar.grid(row=1, column=0, sticky=(E,W)) vScrollbar["command"] = self.packagesView.yview vScrollbar.grid(row=0, column=1, sticky=(N,S)) packagesFrame.columnconfigure(0, weight=1) packagesFrame.rowconfigure(0, weight=1) packagesFrame.grid(row=0, column=1, columnspan=4, sticky=(N, S, E, W), padx=3, pady=3) self.packagesView.focus_set() self.packagesView.column("#0", width=120, anchor="w") self.packagesView.heading("#0", text=_("Name")) self.packagesView["columns"] = ("ver", "status", "date", "update", "descr") self.packagesView.column("ver", width=150, anchor="w", stretch=False) self.packagesView.heading("ver", text=_("Version")) self.packagesView.column("status", width=50, anchor="w", stretch=False) self.packagesView.heading("status", text=_("Status")) self.packagesView.column("date", width=170, anchor="w", stretch=False) self.packagesView.heading("date", text=_("File Date")) self.packagesView.column("update", width=50, anchor="w", stretch=False) self.packagesView.heading("update", text=_("Update")) self.packagesView.column("descr", width=200, anchor="w", stretch=False) self.packagesView.heading("descr", text=_("Description")) remappingsFrame = Frame(frame) vScrollbar = Scrollbar(remappingsFrame, orient=VERTICAL) hScrollbar = Scrollbar(remappingsFrame, orient=HORIZONTAL) self.remappingsView = Treeview(remappingsFrame, xscrollcommand=hScrollbar.set, yscrollcommand=vScrollbar.set, height=5) self.remappingsView.grid(row=0, column=0, sticky=(N, S, E, W)) hScrollbar["command"] = self.remappingsView.xview hScrollbar.grid(row=1, column=0, sticky=(E,W)) vScrollbar["command"] = self.remappingsView.yview vScrollbar.grid(row=0, column=1, sticky=(N,S)) remappingsFrame.columnconfigure(0, weight=1) remappingsFrame.rowconfigure(0, weight=1) remappingsFrame.grid(row=1, column=1, columnspan=4, sticky=(N, S, E, W), padx=3, pady=3) self.remappingsView.focus_set() self.remappingsView.column("#0", width=200, anchor="w") self.remappingsView.heading("#0", text=_("Prefix")) self.remappingsView["columns"] = ("remapping") self.remappingsView.column("remapping", width=500, anchor="w", stretch=False) self.remappingsView.heading("remapping", text=_("Remapping")) # bottom frame package info details packageInfoFrame = Frame(frame, width=700) packageInfoFrame.columnconfigure(1, weight=1) self.packageNameLabel = Label(packageInfoFrame, wraplength=600, justify="left", font=font.Font(family='Helvetica', size=12, weight='bold')) self.packageNameLabel.grid(row=0, column=0, columnspan=6, sticky=W) self.packageVersionHdr = Label(packageInfoFrame, text=_("version:"), state=DISABLED) self.packageVersionHdr.grid(row=1, column=0, sticky=W) self.packageVersionLabel = Label(packageInfoFrame, wraplength=600, justify="left") self.packageVersionLabel.grid(row=1, column=1, columnspan=5, sticky=W) self.packageDescrHdr = Label(packageInfoFrame, text=_("description:"), state=DISABLED) self.packageDescrHdr.grid(row=2, column=0, sticky=W) self.packageDescrLabel = Label(packageInfoFrame, wraplength=600, justify="left") self.packageDescrLabel.grid(row=2, column=1, columnspan=5, sticky=W) self.packagePrefixesHdr = Label(packageInfoFrame, text=_("prefixes:"), state=DISABLED) self.packagePrefixesHdr.grid(row=3, column=0, sticky=W) self.packagePrefixesLabel = Label(packageInfoFrame, wraplength=600, justify="left") self.packagePrefixesLabel.grid(row=3, column=1, columnspan=5, sticky=W) ToolTip(self.packagePrefixesLabel, text=_("List of prefixes that this package remaps."), wraplength=240) self.packageUrlHdr = Label(packageInfoFrame, text=_("URL:"), state=DISABLED) self.packageUrlHdr.grid(row=4, column=0, sticky=W) self.packageUrlLabel = Label(packageInfoFrame, wraplength=600, justify="left") self.packageUrlLabel.grid(row=4, column=1, columnspan=5, sticky=W) ToolTip(self.packageUrlLabel, text=_("URL of taxonomy package (local file path or web loaded file)."), wraplength=240) self.packageDateHdr = Label(packageInfoFrame, text=_("date:"), state=DISABLED) self.packageDateHdr.grid(row=5, column=0, sticky=W) self.packageDateLabel = Label(packageInfoFrame, wraplength=600, justify="left") self.packageDateLabel.grid(row=5, column=1, columnspan=5, sticky=W) ToolTip(self.packageDateLabel, text=_("Date of currently loaded package file (with parenthetical node when an update is available)."), wraplength=240) self.packageEnableButton = Button(packageInfoFrame, text=self.ENABLE, state=DISABLED, command=self.packageEnable) ToolTip(self.packageEnableButton, text=_("Enable/disable package."), wraplength=240) self.packageEnableButton.grid(row=6, column=1, sticky=E) self.packageMoveUpButton = Button(packageInfoFrame, text=_("Move Up"), state=DISABLED, command=self.packageMoveUp) ToolTip(self.packageMoveUpButton, text=_("Move package up (above other remappings)."), wraplength=240) self.packageMoveUpButton.grid(row=6, column=2, sticky=E) self.packageMoveDownButton = Button(packageInfoFrame, text=_("Move Down"), state=DISABLED, command=self.packageMoveDown) ToolTip(self.packageMoveDownButton, text=_("Move package down (below other remappings)."), wraplength=240) self.packageMoveDownButton.grid(row=6, column=3, sticky=E) self.packageReloadButton = Button(packageInfoFrame, text=_("Reload"), state=DISABLED, command=self.packageReload) ToolTip(self.packageReloadButton, text=_("Reload/update package."), wraplength=240) self.packageReloadButton.grid(row=6, column=4, sticky=E) self.packageRemoveButton = Button(packageInfoFrame, text=_("Remove"), state=DISABLED, command=self.packageRemove) ToolTip(self.packageRemoveButton, text=_("Remove package from packages table (does not erase the package file)."), wraplength=240) self.packageRemoveButton.grid(row=6, column=5, sticky=E) packageInfoFrame.grid(row=2, column=0, columnspan=5, sticky=(N, S, E, W), padx=3, pady=3) packageInfoFrame.config(borderwidth=4, relief="groove") okButton = Button(frame, text=_("Close"), command=self.ok) ToolTip(okButton, text=_("Accept and changes (if any) and close dialog."), wraplength=240) cancelButton = Button(frame, text=_("Cancel"), command=self.close) ToolTip(cancelButton, text=_("Cancel changes (if any) and close dialog."), wraplength=240) okButton.grid(row=3, column=3, sticky=(S,E), pady=3) cancelButton.grid(row=3, column=4, sticky=(S,E), pady=3, padx=3) self.loadTreeViews() self.geometry("+{0}+{1}".format(dialogX+50,dialogY+100)) frame.grid(row=0, column=0, sticky=(N,S,E,W)) frame.columnconfigure(0, weight=0) frame.columnconfigure(1, weight=1) frame.rowconfigure(0, weight=1) window = self.winfo_toplevel() window.columnconfigure(0, weight=1) window.rowconfigure(0, weight=1) self.bind("<Return>", self.ok) self.bind("<Escape>", self.close) self.protocol("WM_DELETE_WINDOW", self.close) self.grab_set() self.wait_window(self) def loadTreeViews(self): self.selectedModule = None # clear previous treeview entries for previousNode in self.packagesView.get_children(""): self.packagesView.delete(previousNode) for i, packageInfo in enumerate(self.packagesConfig.get("packages", [])): name = packageInfo.get("name", "package{}".format(i)) node = self.packagesView.insert("", "end", "_{}".format(i), text=name) self.packagesView.set(node, "ver", packageInfo.get("version")) self.packagesView.set(node, "status", packageInfo.get("status")) self.packagesView.set(node, "date", packageInfo.get("fileDate")) if name in self.packageNamesWithNewerFileDates: self.packagesView.set(node, "update", _("available")) self.packagesView.set(node, "descr", packageInfo.get("description")) # clear previous treeview entries for previousNode in self.remappingsView.get_children(""): self.remappingsView.delete(previousNode) for i, remappingItem in enumerate(sorted(self.packagesConfig.get("remappings", {}).items())): prefix, remapping = remappingItem node = self.remappingsView.insert("", "end", prefix, text=prefix) self.remappingsView.set(node, "remapping", remapping) self.packageSelect() # clear out prior selection def ok(self, event=None): if self.packagesConfigChanged: PackageManager.packagesConfig = self.packagesConfig PackageManager.packagesConfigChanged = True self.cntlr.onPackageEnablementChanged() self.close() def close(self, event=None): self.parent.focus_set() self.destroy() def packageSelect(self, *args): node = (self.packagesView.selection() or (None,))[0] try: nodeIndex = int(node[1:]) except (ValueError, TypeError): nodeIndex = -1 if 0 <= nodeIndex < len(self.packagesConfig["packages"]): packageInfo = self.packagesConfig["packages"][nodeIndex] self.selectedPackageIndex = nodeIndex name = packageInfo["name"] self.packageNameLabel.config(text=name) self.packageVersionHdr.config(state=ACTIVE) self.packageVersionLabel.config(text=packageInfo["version"]) self.packageDescrHdr.config(state=ACTIVE) self.packageDescrLabel.config(text=packageInfo["description"]) self.packagePrefixesHdr.config(state=ACTIVE) self.packagePrefixesLabel.config(text=', '.join(packageInfo["remappings"].keys())) self.packageUrlHdr.config(state=ACTIVE) self.packageUrlLabel.config(text=packageInfo["URL"]) self.packageDateHdr.config(state=ACTIVE) self.packageDateLabel.config(text=packageInfo["fileDate"] + " " + (_("(an update is available)") if name in self.packageNamesWithNewerFileDates else "")) self.packageEnableButton.config(state=ACTIVE, text={"enabled":self.DISABLE, "disabled":self.ENABLE}[packageInfo["status"]]) self.packageMoveUpButton.config(state=ACTIVE if 0 < nodeIndex else DISABLED) self.packageMoveDownButton.config(state=ACTIVE if nodeIndex < (len(self.packagesConfig["packages"]) - 1) else DISABLED) self.packageReloadButton.config(state=ACTIVE) self.packageRemoveButton.config(state=ACTIVE) else: self.selectedPackageIndex = -1 self.packageNameLabel.config(text="") self.packageVersionHdr.config(state=DISABLED) self.packageVersionLabel.config(text="") self.packageDescrHdr.config(state=DISABLED) self.packageDescrLabel.config(text="") self.packagePrefixesHdr.config(state=DISABLED) self.packagePrefixesLabel.config(text="") self.packageUrlHdr.config(state=DISABLED) self.packageUrlLabel.config(text="") self.packageDateHdr.config(state=DISABLED) self.packageDateLabel.config(text="") self.packageEnableButton.config(state=DISABLED, text=self.ENABLE) self.packageMoveUpButton.config(state=DISABLED) self.packageMoveDownButton.config(state=DISABLED) self.packageReloadButton.config(state=DISABLED) self.packageRemoveButton.config(state=DISABLED) def findLocally(self): initialdir = self.cntlr.pluginDir # default plugin directory if not self.cntlr.isMac: # can't navigate within app easily, always start in default directory initialdir = self.cntlr.config.setdefault("packageOpenDir", initialdir) filename = self.cntlr.uiFileDialog("open", parent=self, title=_("Choose taxonomy package file"), initialdir=initialdir, filetypes=[(_("Taxonomy package files (*.zip)"), "*.zip"), (_("Manifest (*.taxonomyPackage.xml)"), "*.taxonomyPackage.xml"), (_("Oasis Catalog (*catalog.xml)"), "*catalog.xml")], defaultextension=".zip") if filename: # check if a package is selected (any file in a directory containing an __init__.py self.cntlr.config["packageOpenDir"] = os.path.dirname(filename) packageInfo = PackageManager.packageInfo(filename, packageManifestName=self.manifestNamePattern) self.loadFoundPackageInfo(packageInfo, filename) def findOnWeb(self): url = DialogURL.askURL(self) if url: # url is the in-cache or local file packageInfo = PackageManager.packageInfo(url, packageManifestName=self.manifestNamePattern) self.cntlr.showStatus("") # clear web loading status self.loadFoundPackageInfo(packageInfo, url) def manifestName(self): self.manifestNamePattern = simpledialog.askstring(_("Archive manifest file name pattern"), _("Provide non-standard archive manifest file name pattern (e.g., *taxonomyPackage.xml). \n" "Uses unix file name pattern matching. \n" "Multiple manifest files are supported in archive (such as oasis catalogs). \n" "(If blank, search for either .taxonomyPackage.xml or catalog.xml). "), initialvalue=self.manifestNamePattern, parent=self) def loadFoundPackageInfo(self, packageInfo, url): if packageInfo and packageInfo.get("name"): self.addPackageInfo(packageInfo) self.loadTreeViews() else: messagebox.showwarning(_("Package is not itself a taxonomy package. "), _("File does not itself contain a manifest file: \n\n{0}\n\n " "If opening an archive file, the manifest file search pattern currently is \"\", please press \"Manifest\" to change manifest file name pattern, e.g.,, \"*.taxonomyPackage.xml\", if needed. ") .format(url), parent=self) def removePackageInfo(self, name, version): # find package entry packagesList = self.packagesConfig["packages"] j = -1 for i, packageInfo in enumerate(packagesList): if packageInfo['name'] == name and packageInfo['version'] == version: j = i break if 0 <= j < len(packagesList): del self.packagesConfig["packages"][i] self.packagesConfigChanged = True def addPackageInfo(self, packageInfo): name = packageInfo["name"] version = packageInfo["version"] self.removePackageInfo(name, version) # remove any prior entry for this package self.packageNamesWithNewerFileDates.discard(name) # no longer has an update available self.packagesConfig["packages"].append(packageInfo) PackageManager.rebuildRemappings() self.packagesConfigChanged = True def packageEnable(self): if 0 <= self.selectedPackageIndex < len(self.packagesConfig["packages"]): packageInfo = self.packagesConfig["packages"][self.selectedPackageIndex] if self.packageEnableButton['text'] == self.ENABLE: packageInfo["status"] = "enabled" self.packageEnableButton['text'] = self.DISABLE elif self.packageEnableButton['text'] == self.DISABLE: packageInfo["status"] = "disabled" self.packageEnableButton['text'] = self.ENABLE self.packagesConfigChanged = True PackageManager.rebuildRemappings() self.loadTreeViews() def packageMoveUp(self): if 1 <= self.selectedPackageIndex < len(self.packagesConfig["packages"]): packages = self.packagesConfig["packages"] packageInfo = packages[self.selectedPackageIndex] del packages[self.selectedPackageIndex] packages.insert(self.selectedPackageIndex -1, packageInfo) self.packagesConfigChanged = True PackageManager.rebuildRemappings() self.loadTreeViews() def packageMoveDown(self): if 0 <= self.selectedPackageIndex < len(self.packagesConfig["packages"]) - 1: packages = self.packagesConfig["packages"] packageInfo = packages[self.selectedPackageIndex] del packages[self.selectedPackageIndex] packages.insert(self.selectedPackageIndex + 1, packageInfo) self.packagesConfigChanged = True PackageManager.rebuildRemappings() self.loadTreeViews() def packageReload(self): if 0 <= self.selectedPackageIndex < len(self.packagesConfig["packages"]): packageInfo = self.packagesConfig["packages"][self.selectedPackageIndex] url = packageInfo.get("URL") if url: packageInfo = PackageManager.packageInfo(url, reload=True, packageManifestName=packageInfo.get("manifestName")) if packageInfo: self.addPackageInfo(packageInfo) PackageManager.rebuildRemappings() self.loadTreeViews() self.cntlr.showStatus(_("{0} reloaded").format(packageInfo.get("name")), clearAfter=5000) else: messagebox.showwarning(_("Package error"), _("File or package cannot be reloaded: \n\n{0}") .format(url), parent=self) def packageRemove(self): if 0 <= self.selectedPackageIndex < len(self.packagesConfig["packages"]): packageInfo = self.packagesConfig["packages"][self.selectedPackageIndex] self.removePackageInfo(packageInfo["name"], packageInfo["version"]) self.packagesConfigChanged = True PackageManager.rebuildRemappings() self.loadTreeViews()
class SolutionTabFrame(Frame): ''' This class is responsible for displaying solution on the screen. It extends Frame class. Attributes: parent (Tk object that can contain Frame): parent that can contain Frame, MUST implement method change_solution_tab_name(str). data_from_file_lbl (Label): label that contains file name with data if specified. solution_tab (SolutionFrameWithText): notebook with tabs describing solution. model_solutions (list of Solution): list with one or more solutions that have been generated after running algorithm. param_strs (list of str): list with strings that should appear before printing every solution from model_solutions. ranks (list of list of int): list of ranks corresponding to every solution from model_solutions, ranks are generated by peel-the-onion algorithm. categorical (str): name of the categorical variable used in categorical analysis. progress_bar (Progressbar): progress bar to show how solution is loaded or saved to file. status_lbl (Label): label for displaying solution status. solution_format_var (IntVar): IntVar object that tracks which file format is chosen for solution. ''' def __init__(self, parent, *args, **kw): super().__init__(parent, *args, **kw) self.parent = parent self.data_from_file_lbl = None self.solution_tab = None self.model_solutions = None self.param_strs = None self.ranks = None self.params = None self.categorical = None self.run_date = None self.total_seconds = 0 self.progress_bar = None self.status_lbl = None self.solution_format_var = IntVar() self.create_widgets() def create_widgets(self): ''' Creates appropriate widgets on this frame. ''' self.columnconfigure(0, weight=1) self.rowconfigure(3, weight=1) frame_for_save_btn = Frame(self) frame_for_save_btn.columnconfigure(1, weight=1) self.status_lbl = Label(frame_for_save_btn, text='') self.status_lbl.grid(row=0, column=1, sticky=N + W) save_solution_btn = Button(frame_for_save_btn, text='Save solution', command=self.on_save_solution) save_solution_btn.grid(row=1, column=0, sticky=W + N, padx=5, pady=5) self.progress_bar = Progressbar(frame_for_save_btn, mode='determinate', maximum=100) self.progress_bar.grid(row=1, column=1, sticky=W + E, padx=10, pady=5) frame_for_save_btn.grid(sticky=W + N + E + S, padx=5, pady=5) frame_for_btns = Frame(self) self._create_file_format_btn('*.xlsx', 1, frame_for_btns, 0) self._create_file_format_btn('*.xls', 2, frame_for_btns, 1) self._create_file_format_btn('*.csv', 3, frame_for_btns, 2) self.solution_format_var.set(1) frame_for_btns.grid(row=1, column=0, sticky=W + N + E + S, padx=5, pady=5) self.data_from_file_lbl = Label(self, text=TEXT_FOR_FILE_LBL, anchor=W, justify=LEFT, wraplength=MAX_FILE_PARAMS_LBL_LENGTH) self.data_from_file_lbl.grid(row=2, column=0, padx=5, pady=5, sticky=W + N) self.solution_tab = SolutionFrameWithText(self) self.solution_tab.grid(row=3, column=0, sticky=W + E + S + N, padx=5, pady=5) def _create_file_format_btn(self, btn_text, var_value, parent, column): ''' Creates and grids Radiobutton used for choosing solution file format. Args: btn_text (str): text displayed next to the Radiobutton. var_value (int): value of the IntVar associated with this Radiobutton. parent (Tk object): parent of this Radiobutton. column (int): column index where this Radiobutton should be gridded. ''' sol_format_btn = Radiobutton(parent, text=btn_text, variable=self.solution_format_var, value=var_value) sol_format_btn.grid(row=2, column=column, sticky=W + N, padx=2) def on_save_solution(self): ''' Saves solution to file. This method is called when save solution button is pressed. If there is a solution, this method will ask user to provide a file name where solution should be stored. If a valid name is provided, solution is saved to that file. Allowed file formats are: .xls and .xlsx. Default file extension is .xlsx. If the user checked 'csv' as solution output format, then the user will be asked to choose a directory where all csv files will be written. ''' if self.model_solutions is not None: assert (self.param_strs is not None) if (self.solution_format_var.get() == 1 or self.solution_format_var.get() == 2): file_name = self.ask_file_name_to_save( self.solution_format_var.get()) dir_name = '' else: dir_name = askdirectory() file_name = '' if file_name or dir_name: print(file_name) self.status_lbl.config(text='Saving solution to file...') if file_name.endswith('.xls'): work_book = xlwt.Workbook() elif file_name.endswith('.xlsx'): work_book = XlsxWorkbook() else: # all not supported formats will be written to csv assert (dir_name) work_book = TxtWriter(dir_name) writer = XLSWriter(self.params, work_book, self.run_date, self.total_seconds, ranks=self.ranks, categorical=self.categorical) nb_models = len(self.model_solutions) # +1 for parameters sheet, it is stored separately nb_sheets = len(writer.worksheets) + 1 progress_recorder = GuiProgress(self.progress_bar, nb_models, nb_sheets) try: for count, sol in enumerate(self.model_solutions): writer.write_data(sol, self.param_strs[count], progress_recorder) work_book.save(file_name) except ValueError: # can happen if maximum number of rows is exceeded self.status_lbl.config( text='File is too large for xls format,' ' it will be saved to csv instead') work_book = TxtWriter(os.path.splitext(file_name)[0]) writer = XLSWriter(self.params, work_book, self.run_date, self.total_seconds, ranks=self.ranks, categorical=self.categorical) progress_recorder.set_position(0) for count, sol in enumerate(self.model_solutions): writer.write_data(sol, self.param_strs[count], progress_recorder) work_book.save(file_name) progress_recorder.set_position(100) self.parent.change_solution_tab_name('Solution') self.status_lbl.config(text='Solution saved') def ask_file_name_to_save(self, ext_code): ''' Calls asksaveasfilename dialogue to ask the user where file should be saved. If file without extension is entered, default extension will be used (.xlsx). This method is used to mock this object for unit tests. Args: ext_code (int): code for file extension 1 - xlsx, 2 - xls. ''' if ext_code == 1: filetype = SOLUTION_XLSX_FILE else: filetype = SOLUTION_XLS_FILE return asksaveasfilename(filetypes=filetype, defaultextension='xlsx') def show_solution(self, solutions, params, param_strs, run_date, total_seconds, ranks=None, categorical=None): ''' Displays solution on the screen. Args: solutions (list of Solution): list of solutions (might contain just one solution) that have been generated after running algorithm. params (Parameters): object with parameters that will be written to file on the Parameters page. param_strs (list of str): list with strings that should appear before printing every solution from model_solutions. ranks (list of list of int): list of ranks corresponding to every solution from model_solutions, ranks are generated by peel-the-onion algorithm. categorical (str): name of the categorical variable used in categorical analysis. ''' self.status_lbl.config(text='') self.model_solutions = solutions self.param_strs = param_strs self.ranks = ranks self.params = params self.categorical = categorical self.run_date = run_date self.total_seconds = total_seconds self.status_lbl.config(text='Loading solution...') self.solution_tab.show_solution(solutions, params, param_strs, run_date, total_seconds, ranks, categorical) self.parent.change_solution_tab_name('Solution*') self.status_lbl.config(text='Solution loaded') def update_data_file_name(self, new_data_file_name): ''' Updates label with data file name. Args: new_data_file_name (str): new value of the data file name ''' self.data_from_file_lbl.config(text=TEXT_FOR_FILE_LBL + new_data_file_name)
class Download(Frame): def __init__(self, master, **kwargs): super(Download, self).__init__(master, borderwidth=20, **kwargs) self.fs = None self.tree = None self.logfile = None # User informations self.info_tree = False self.start_time = None info = Frame(self, borderwidth=10) self.info_label = Label(info, wraplength=350, borderwidth=20, justify='center', font=('a', 10, 'bold')) self.info_indis = Label(info) self.info_fams = Label(info) self.time = Label(info) self.info_label.grid(row=0, column=0, columnspan=2) self.info_indis.grid(row=1, column=0) self.info_fams.grid(row=1, column=1) self.time.grid(row=3, column=0, columnspan=2) self.form = Frame(self) self.sign_in = SignIn(self.form) self.options = None self.title = Label(self, text=_('Sign In to FamilySearch'), font=('a', 12, 'bold')) buttons = Frame(self) self.btn_quit = Button(buttons, text=_('Quit'), command=Thread(target=self.quit).start) self.btn_valid = Button(buttons, text=_('Sign In'), command=self.command_in_thread(self.login)) self.title.pack() self.sign_in.pack() self.form.pack() self.btn_quit.pack(side='left', padx=(0, 40)) self.btn_valid.pack(side='right', padx=(40, 0)) info.pack() buttons.pack(side='bottom') self.pack() self.update_needed = False def info(self, text): self.info_label.config(text=text) def save(self): filename = filedialog.asksaveasfilename(title=_('Save as'), defaultextension='.csv', filetypes=(('CSV', '.csv'), (_('All files'), '*.*'))) if not filename: return #with open(filename, 'w', encoding='utf-8') as file: #self.tree.print(file) fh = open(filename, "w") fh.write('personnum') fh.write(';') fh.write('given names') fh.write(';') fh.write('surname') fh.write(';') fh.write('gender') fh.write(';') fh.write('birthdate') fh.write(';') fh.write('birthplace') fh.write(';') fh.write('deathdate') fh.write(';') fh.write('deathplace') fh.write(';') fh.write('fathernum') fh.write(';') fh.write('mothernum') fh.write(';') fh.write('spousenum') fh.write(';') fh.write('childnum') fh.write(';') fh.write('Life Summary') fh.write('\n') for fid in sorted(self.tree.indi, key=lambda x: self.tree.indi.__getitem__(x).num): #person number personnum = self.tree.indi[fid].fid #name givennames = self.tree.indi[fid].name.given #surname, all caps surname = self.tree.indi[fid].name.surname #gender gender = self.tree.indi[fid].gender #birth and death birthstring = 'b. ' deathstring = 'd. ' birthdate = '' birthplace = '' deathdate = '' deathplace = '' for o in self.tree.indi[fid].facts: if o.type == 'http://gedcomx.org/Birth': if o.date: birthdate = o.date birthstring = birthstring + o.date if o.place: birthplace = o.place birthstring = birthstring + ' in ' + o.place if o.type == 'http://gedcomx.org/Death': if o.date: deathdate = o.date deathstring = deathstring + o.date if o.place: deathplace = o.place deathstring = deathstring + ' in ' + o.place fathernum = '' mothernum = '' for p in self.tree.indi[fid].parents: #father number fathernum = p[0] #mother number mothernum = p[1] spousenum = '' childnum = '' childset = '' for husb, wife in sorted( self.tree.fam, key=lambda x: self.tree.fam.__getitem__(x).num): if self.tree.fam[(husb, wife)].husb_fid == fid: childnum = self.tree.fam[(husb, wife)].chil_fid.pop() self.tree.fam[(husb, wife)].chil_fid.add(childnum) spousenum = self.tree.fam[(husb, wife)].wife_fid elif self.tree.fam[(husb, wife)].wife_fid == fid: childnum = self.tree.fam[(husb, wife)].chil_fid.pop() self.tree.fam[(husb, wife)].chil_fid.add(childnum) spousenum = self.tree.fam[(husb, wife)].husb_fid else: continue #print('') #print(personnum) #print(givennames + ' ' + surname) #print(surname.upper()) #print(birthstring) #print(deathstring) #print(fathernum) #print(mothernum) #print(spousenum) #print(childnum) #print('Life Summary ...') #Print out in semicolon-csv format if personnum: fh.write(personnum) fh.write(';') if givennames: fh.write(givennames) fh.write(';') if surname: fh.write(surname) fh.write(';') if gender: fh.write(gender) fh.write(';') if birthdate: fh.write(birthdate) fh.write(';') if birthplace: fh.write(birthplace) fh.write(';') if deathdate: fh.write(deathdate) fh.write(';') if deathplace: fh.write(deathplace) fh.write(';') if fathernum: fh.write(fathernum) fh.write(';') if mothernum: fh.write(mothernum) fh.write(';') if spousenum: fh.write(spousenum) fh.write(';') if childnum: fh.write(childnum) fh.write(';') fh.write('') fh.write('\n') fh.close() def login(self): global _ username = self.sign_in.username.get() password = self.sign_in.password.get() if not (username and password): messagebox.showinfo(message=_( 'Please enter your FamilySearch username and password.')) return self.btn_valid.config(state='disabled') self.info(_('Login to FamilySearch...')) self.logfile = open('download.log', 'w', encoding='utf-8') self.fs = Session(self.sign_in.username.get(), self.sign_in.password.get(), verbose=True, logfile=self.logfile, timeout=1) if not self.fs.logged: messagebox.showinfo( _('Error'), message=_('The username or password was incorrect')) self.btn_valid.config(state='normal') self.info('') return self.tree = Tree(self.fs) _ = self.fs._ self.title.config(text=_('Options')) cache.delete('lang') cache.add('lang', self.fs.lang) lds_account = self.fs.get_url( '/platform/tree/persons/%s/ordinances' % self.fs.fid) != 'error' self.options = Options(self.form, lds_account) self.info('') self.sign_in.destroy() self.options.pack() self.master.change_lang() self.btn_valid.config(command=self.command_in_thread(self.download), state='normal', text=_('Download')) self.options.start_indis.add_indi(self.fs.fid) self.update_needed = False def quit(self): self.update_needed = False if self.logfile: self.logfile.close() super(Download, self).quit() # prevent exception during download os._exit(1) def download(self): todo = [ self.options.start_indis.indis[key] for key in sorted(self.options.start_indis.indis) ] for fid in todo: if not re.match(r'[A-Z0-9]{4}-[A-Z0-9]{3}', fid): messagebox.showinfo(_('Error'), message=_('Invalid FamilySearch ID: ') + fid) return self.start_time = time.time() self.options.destroy() self.form.destroy() self.title.config(text='Ancestor Cards') self.btn_valid.config(state='disabled') self.info(_('Download starting individuals...')) self.info_tree = True self.tree.add_indis(todo) # download ancestors #todo = set(todo) todo = set(self.tree.indi.keys()) done = set() for i in range(self.options.ancestors.get()): if not todo: break done |= todo #self.info(_('Download ') + str(i + 1) + _('th generation of ancestors...')) print(_("Downloading %s. of generations of ancestors...") % (i + 1), file=sys.stderr) todo = self.tree.add_parents(todo) - done #todo = set(self.tree.indi.keys()) #done = set() #for i in range(self.options.descendants.get()): # if not todo: # break # done |= todo # self.info(_('Download ') + str(i + 1) + _('th generation of descendants...')) # todo = self.tree.add_children(todo) - done #if self.options.spouses.get(): # self.info(_('Download spouses and marriage information...')) # todo = set(self.tree.indi.keys()) # self.tree.add_spouses(todo) self.tree.reset_num() self.btn_valid.config(command=self.save, state='normal', text=_('Save')) self.info(text=_('Success ! Click below to save your CSV file')) self.update_info_tree() self.update_needed = False def command_in_thread(self, func): def res(): self.update_needed = True Thread(target=self.update_gui).start() Thread(target=func).start() return res def update_info_tree(self): if self.info_tree and self.start_time and self.tree: self.info_indis.config(text=_('Individuals: %s') % len(self.tree.indi)) self.info_fams.config(text=_('Families: %s') % len(self.tree.fam)) t = round(time.time() - self.start_time) minutes = t // 60 seconds = t % 60 self.time.config(text=_('Elapsed time: %s:%s') % (minutes, '00%s'[len(str(seconds)):] % seconds)) def update_gui(self): while self.update_needed: self.update_info_tree() self.master.update() time.sleep(0.1)
class FrameDownload(Frame): def __init__(self, master=None, option=()): super().__init__(master=master) self.master = master self.master.title('Download information') self.option = option self.setupUI() def setupUI(self): # build UI base on URLS if self.option[2] == SEARCH: # title window label_title = Label(self, text='Search Photos') label_title.config(anchor='center', foreground='white', background='#8e44ad') label_title.grid(row=0, column=0, columnspan=6, sticky='we') # progress self.progress = Progressbar(self) self.progress.config(orient='horizontal', length=100, mode='determinate') self.progress.grid(row=2, column=0, columnspan=5, sticky='we') self.var_progress = StringVar() self.var_progress.set('0%') self.label_show_progress = Label(self) self.label_show_progress.config(textvariable=self.var_progress, anchor='center') self.label_show_progress.var = self.var_progress self.label_show_progress.grid(row=2, column=5, sticky='w') # query self.label_query = Label(self, text='Query') self.label_query.grid(row=1, column=0, sticky='e') self.var_entry_query = StringVar() self.entry_query = Entry(self) self.entry_query.config(textvariable=self.var_entry_query, state='readonly') self.entry_query.grid(row=1, column=1, sticky='w') # total self.var_total = StringVar() self.var_total.set('Total') self.label_total = Label(self, textvariable=self.var_total) self.label_total.grid(row=1, column=2, sticky='e') self.var_entry_total = IntVar() self.entry_total = Entry(self) self.entry_total.config(textvariable=self.var_entry_total, state='readonly') self.entry_total.grid(row=1, column=3, sticky='w') # total pages self.label_total_page = Label(self, text='Total pages:') self.label_total_page.grid(row=1, column=4, sticky='e') self.var_entry_total_pages = IntVar() self.entry_total_page = Entry(self) self.entry_total_page.config(textvariable=self.var_entry_total_pages, state='readonly') self.entry_total_page.grid(row=1, column=5, sticky='w') # show image is downloaded self.label_image_downloaded = Label(self, anchor='center') self.label_image_downloaded.grid(row=3, column=0, columnspan=6, sticky='wesn') # self.change_ui() elif self.option[2] == LIST: # title window label_title = Label(self, text='List of Photos') label_title.config( anchor='center', foreground='white', background='#2c3e50') label_title.grid(row=0, column=0, columnspan=4, sticky='we') # progress self.progress = Progressbar(self) self.progress.config(orient='horizontal', length=100, mode='determinate') self.progress.grid(row=2, column=0, columnspan=3, sticky='we') self.var_progress = StringVar() self.var_progress.set('0%') self.label_show_progress = Label(self) self.label_show_progress.config( textvariable=self.var_progress, anchor='center') self.label_show_progress.var = self.var_progress self.label_show_progress.grid(row=2, column=3, sticky='w') # query self.label_query = Label(self, text='Query:') self.label_query.grid(row=1, column=0, sticky='e') self.entry_query = Entry(self) self.entry_query.insert(0,'LIST') self.entry_query.config(state='readonly') self.entry_query.grid(row=1, column=1, sticky='w') # amount self.label_total = Label(self, text='Amount:') self.label_total.grid(row=1, column=2, sticky='e') self.entry_total = Entry(self) self.entry_total.insert(0,self.option[3]['per_page']) self.entry_total.config(state='readonly') self.entry_total.grid(row=1, column=3, sticky='w') # show image is downloaded self.label_image_downloaded = Label(self, anchor='center') self.label_image_downloaded.grid( row=3, column=0, columnspan=4, sticky='wesn') # self.change_ui() elif self.option[2] == RANDOM: # title window label_title = Label(self, text='Random Photos') label_title.config( anchor='center', foreground='white', background='#16a085') label_title.grid(row=0, column=0, columnspan=4, sticky='we') # progress self.progress = Progressbar(self) self.progress.config(orient='horizontal', length=100, mode='determinate') self.progress.grid(row=2, column=0, columnspan=3, sticky='we') self.var_progress = StringVar() self.var_progress.set('0%') self.label_show_progress = Label(self) self.label_show_progress.config( textvariable=self.var_progress, anchor='center') self.label_show_progress.var = self.var_progress self.label_show_progress.grid(row=2, column=3, sticky='w') # query self.label_query = Label(self, text='Query') self.label_query.grid(row=1, column=0, sticky='e') self.entry_query = Entry(self) self.entry_query.insert(0,'RANDOM') self.entry_query.config(state='readonly') self.entry_query.grid(row=1, column=1, sticky='w') # amount self.label_total = Label(self, text='Amount') self.label_total.grid(row=1, column=2, sticky='e') self.var_entry_total = IntVar() if self.option[3]['count'] > 30: self.var_entry_total.set(30) else: self.var_entry_total.set(self.option[3]['count']) self.entry_total = Entry(self) self.entry_total.config(textvariable=self.var_entry_total, state='readonly') self.entry_total.grid(row=1, column=3, sticky='w') # show image is downloaded self.label_image_downloaded = Label(self, anchor='center') self.label_image_downloaded.grid( row=3, column=0, columnspan=4, sticky='wesn') def change_ui(self): if self.option[2] == SEARCH: r = requests.get(self.option[2], params=self.option[3]) if r.status_code == 200: # get urls based on quality j = json.loads(r.text) total = j['total'] total_pages = j['total_pages'] results = j['results'] self.var_entry_query.set(self.option[3]['query']) self.var_entry_total.set(total) self.var_entry_total_pages.set(total_pages) self.entry_query.update_idletasks() self.entry_total.update_idletasks() self.entry_total_page.update_idletasks() # random photos elif self.option[2] == RANDOM: r = requests.get(self.option[2], params=self.option[3]) if r.status_code == 200: # get result j = json.loads(r.text) results = j elif self.option[2] == LIST: r = requests.get(self.option[2], params=self.option[3]) if r.status_code == 200: # get result j = json.loads(r.text) results = j self.download(results) def download(self, results): for i in results: name = i['id'] url = i['urls'][self.option[1]] time.sleep(1) # delay time to send request try: request.urlretrieve(url, self.option[0]+'/'+name+'.jpg') except Exception as x: # re download if have a problem print('have problem', x) time.sleep(1) self.progress['value'] += 100/len(results) self.var_progress.set('{}%'.format(self.progress['value'])) # show image downloaded image = Image.open(self.option[0]+'/'+name+'.jpg') width = int(self.winfo_width()) height = int(width*image.height/image.width) self.photo = ImageTk.PhotoImage( image.resize((width, height), Image.ANTIALIAS)) self.label_image_downloaded.config(image=self.photo) self.label_image_downloaded.image = self.photo self.progress.update_idletasks() self.message_done = messagebox.showinfo('Info', 'Done') self.master.destroy()
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 DialogPluginManager(Toplevel): def __init__(self, mainWin, modulesWithNewerFileDates): super(DialogPluginManager, self).__init__(mainWin.parent) self.ENABLE = _("Enable") self.DISABLE = _("Disable") self.parent = mainWin.parent self.cntlr = mainWin # copy plugins for temporary display self.pluginConfig = PluginManager.pluginConfig self.pluginConfigChanged = False self.uiClassMethodsChanged = False self.modelClassesChanged = False self.disclosureSystemTypesChanged = False self.hostSystemFeaturesChanged = False self.modulesWithNewerFileDates = modulesWithNewerFileDates parentGeometry = re.match("(\d+)x(\d+)[+]?([-]?\d+)[+]?([-]?\d+)", self.parent.geometry()) dialogX = int(parentGeometry.group(3)) dialogY = int(parentGeometry.group(4)) self.title(_("Plug-in Manager")) frame = Frame(self) # left button frame buttonFrame = Frame(frame, width=40) buttonFrame.columnconfigure(0, weight=1) addLabel = Label(buttonFrame, text=_("Find plug-in modules:"), wraplength=60, justify="center") addLocalButton = Button(buttonFrame, text=_("Locally"), command=self.findLocally) ToolTip(addLocalButton, text=_("File chooser allows selecting python module files to add (or reload) plug-ins, from the local file system."), wraplength=240) addWebButton = Button(buttonFrame, text=_("On Web"), command=self.findOnWeb) ToolTip(addWebButton, text=_("Dialog to enter URL full path to load (or reload) plug-ins, from the web or local file system."), wraplength=240) addLabel.grid(row=0, column=0, pady=4) addLocalButton.grid(row=1, column=0, pady=4) addWebButton.grid(row=2, column=0, pady=4) buttonFrame.grid(row=0, column=0, rowspan=2, sticky=(N, S, W), padx=3, pady=3) # right tree frame (plugins already known to arelle) modulesFrame = Frame(frame, width=700) vScrollbar = Scrollbar(modulesFrame, orient=VERTICAL) hScrollbar = Scrollbar(modulesFrame, orient=HORIZONTAL) self.modulesView = Treeview(modulesFrame, xscrollcommand=hScrollbar.set, yscrollcommand=vScrollbar.set, height=7) self.modulesView.grid(row=0, column=0, sticky=(N, S, E, W)) self.modulesView.bind('<<TreeviewSelect>>', self.moduleSelect) hScrollbar["command"] = self.modulesView.xview hScrollbar.grid(row=1, column=0, sticky=(E,W)) vScrollbar["command"] = self.modulesView.yview vScrollbar.grid(row=0, column=1, sticky=(N,S)) modulesFrame.columnconfigure(0, weight=1) modulesFrame.rowconfigure(0, weight=1) modulesFrame.grid(row=0, column=1, columnspan=4, sticky=(N, S, E, W), padx=3, pady=3) self.modulesView.focus_set() self.modulesView.column("#0", width=120, anchor="w") self.modulesView.heading("#0", text=_("Name")) self.modulesView["columns"] = ("author", "ver", "status", "date", "update", "descr", "license") self.modulesView.column("author", width=100, anchor="w", stretch=False) self.modulesView.heading("author", text=_("Author")) self.modulesView.column("ver", width=50, anchor="w", stretch=False) self.modulesView.heading("ver", text=_("Version")) self.modulesView.column("status", width=50, anchor="w", stretch=False) self.modulesView.heading("status", text=_("Status")) self.modulesView.column("date", width=70, anchor="w", stretch=False) self.modulesView.heading("date", text=_("File Date")) self.modulesView.column("update", width=50, anchor="w", stretch=False) self.modulesView.heading("update", text=_("Update")) self.modulesView.column("descr", width=200, anchor="w", stretch=False) self.modulesView.heading("descr", text=_("Description")) self.modulesView.column("license", width=70, anchor="w", stretch=False) self.modulesView.heading("license", text=_("License")) classesFrame = Frame(frame) vScrollbar = Scrollbar(classesFrame, orient=VERTICAL) hScrollbar = Scrollbar(classesFrame, orient=HORIZONTAL) self.classesView = Treeview(classesFrame, xscrollcommand=hScrollbar.set, yscrollcommand=vScrollbar.set, height=5) self.classesView.grid(row=0, column=0, sticky=(N, S, E, W)) hScrollbar["command"] = self.classesView.xview hScrollbar.grid(row=1, column=0, sticky=(E,W)) vScrollbar["command"] = self.classesView.yview vScrollbar.grid(row=0, column=1, sticky=(N,S)) classesFrame.columnconfigure(0, weight=1) classesFrame.rowconfigure(0, weight=1) classesFrame.grid(row=1, column=1, columnspan=4, sticky=(N, S, E, W), padx=3, pady=3) self.classesView.focus_set() self.classesView.column("#0", width=200, anchor="w") self.classesView.heading("#0", text=_("Class")) self.classesView["columns"] = ("modules",) self.classesView.column("modules", width=500, anchor="w", stretch=False) self.classesView.heading("modules", text=_("Modules")) # bottom frame module info details moduleInfoFrame = Frame(frame, width=700) moduleInfoFrame.columnconfigure(1, weight=1) self.moduleNameLabel = Label(moduleInfoFrame, wraplength=600, justify="left", font=font.Font(family='Helvetica', size=12, weight='bold')) self.moduleNameLabel.grid(row=0, column=0, columnspan=4, sticky=W) self.moduleAuthorHdr = Label(moduleInfoFrame, text=_("author:"), state=DISABLED) self.moduleAuthorHdr.grid(row=1, column=0, sticky=W) self.moduleAuthorLabel = Label(moduleInfoFrame, wraplength=600, justify="left") self.moduleAuthorLabel.grid(row=1, column=1, columnspan=3, sticky=W) self.moduleDescrHdr = Label(moduleInfoFrame, text=_("description:"), state=DISABLED) self.moduleDescrHdr.grid(row=2, column=0, sticky=W) self.moduleDescrLabel = Label(moduleInfoFrame, wraplength=600, justify="left") self.moduleDescrLabel.grid(row=2, column=1, columnspan=3, sticky=W) self.moduleClassesHdr = Label(moduleInfoFrame, text=_("classes:"), state=DISABLED) self.moduleClassesHdr.grid(row=3, column=0, sticky=W) self.moduleClassesLabel = Label(moduleInfoFrame, wraplength=600, justify="left") self.moduleClassesLabel.grid(row=3, column=1, columnspan=3, sticky=W) ToolTip(self.moduleClassesLabel, text=_("List of classes that this plug-in handles."), wraplength=240) self.moduleUrlHdr = Label(moduleInfoFrame, text=_("URL:"), state=DISABLED) self.moduleUrlHdr.grid(row=4, column=0, sticky=W) self.moduleUrlLabel = Label(moduleInfoFrame, wraplength=600, justify="left") self.moduleUrlLabel.grid(row=4, column=1, columnspan=3, sticky=W) ToolTip(self.moduleUrlLabel, text=_("URL of plug-in module (local file path or web loaded file)."), wraplength=240) self.moduleDateHdr = Label(moduleInfoFrame, text=_("date:"), state=DISABLED) self.moduleDateHdr.grid(row=5, column=0, sticky=W) self.moduleDateLabel = Label(moduleInfoFrame, wraplength=600, justify="left") self.moduleDateLabel.grid(row=5, column=1, columnspan=3, sticky=W) ToolTip(self.moduleDateLabel, text=_("Date of currently loaded module file (with parenthetical node when an update is available)."), wraplength=240) self.moduleLicenseHdr = Label(moduleInfoFrame, text=_("license:"), state=DISABLED) self.moduleLicenseHdr.grid(row=6, column=0, sticky=W) self.moduleLicenseLabel = Label(moduleInfoFrame, wraplength=600, justify="left") self.moduleLicenseLabel.grid(row=6, column=1, columnspan=3, sticky=W) self.moduleImportsHdr = Label(moduleInfoFrame, text=_("imports:"), state=DISABLED) self.moduleImportsHdr.grid(row=7, column=0, sticky=W) self.moduleImportsLabel = Label(moduleInfoFrame, wraplength=600, justify="left") self.moduleImportsLabel.grid(row=7, column=1, columnspan=3, sticky=W) self.moduleEnableButton = Button(moduleInfoFrame, text=self.ENABLE, state=DISABLED, command=self.moduleEnable) ToolTip(self.moduleEnableButton, text=_("Enable/disable plug in."), wraplength=240) self.moduleEnableButton.grid(row=8, column=1, sticky=E) self.moduleReloadButton = Button(moduleInfoFrame, text=_("Reload"), state=DISABLED, command=self.moduleReload) ToolTip(self.moduleReloadButton, text=_("Reload/update plug in."), wraplength=240) self.moduleReloadButton.grid(row=8, column=2, sticky=E) self.moduleRemoveButton = Button(moduleInfoFrame, text=_("Remove"), state=DISABLED, command=self.moduleRemove) ToolTip(self.moduleRemoveButton, text=_("Remove plug in from plug in table (does not erase the plug in's file)."), wraplength=240) self.moduleRemoveButton.grid(row=8, column=3, sticky=E) moduleInfoFrame.grid(row=2, column=0, columnspan=5, sticky=(N, S, E, W), padx=3, pady=3) moduleInfoFrame.config(borderwidth=4, relief="groove") okButton = Button(frame, text=_("Close"), command=self.ok) ToolTip(okButton, text=_("Accept and changes (if any) and close dialog."), wraplength=240) cancelButton = Button(frame, text=_("Cancel"), command=self.close) ToolTip(cancelButton, text=_("Cancel changes (if any) and close dialog."), wraplength=240) okButton.grid(row=3, column=3, sticky=(S,E), pady=3) cancelButton.grid(row=3, column=4, sticky=(S,E), pady=3, padx=3) enableDisableFrame = Frame(frame) enableDisableFrame.grid(row=3, column=1, sticky=(S,W), pady=3) enableAllButton = Button(enableDisableFrame, text=_("Enable All"), command=self.enableAll) ToolTip(enableAllButton, text=_("Enable all plug ins."), wraplength=240) disableAllButton = Button(enableDisableFrame, text=_("Disable All"), command=self.disableAll) ToolTip(disableAllButton, text=_("Disable all plug ins."), wraplength=240) enableAllButton.grid(row=1, column=1) disableAllButton.grid(row=1, column=2) self.loadTreeViews() self.geometry("+{0}+{1}".format(dialogX+50,dialogY+100)) frame.grid(row=0, column=0, sticky=(N,S,E,W)) frame.columnconfigure(0, weight=0) frame.columnconfigure(1, weight=1) frame.rowconfigure(0, weight=1) window = self.winfo_toplevel() window.columnconfigure(0, weight=1) window.rowconfigure(0, weight=1) self.bind("<Return>", self.ok) self.bind("<Escape>", self.close) self.protocol("WM_DELETE_WINDOW", self.close) self.grab_set() self.wait_window(self) def loadTreeViews(self): self.selectedModule = None # clear previous treeview entries for previousNode in self.modulesView.get_children(""): self.modulesView.delete(previousNode) def loadSubtree(parentNode, moduleItems): for moduleItem in sorted(moduleItems, key=lambda item: item[0]): moduleInfo = moduleItem[1] if parentNode or not moduleInfo.get("isImported"): nodeName = moduleItem[0] if parentNode: nodeName = parentNode + GROUPSEP + nodeName name = moduleInfo.get("name", nodeName) node = self.modulesView.insert(parentNode, "end", nodeName, text=name) self.modulesView.set(node, "author", moduleInfo.get("author")) self.modulesView.set(node, "ver", moduleInfo.get("version")) self.modulesView.set(node, "status", moduleInfo.get("status")) self.modulesView.set(node, "date", moduleInfo.get("fileDate")) if name in self.modulesWithNewerFileDates: self.modulesView.set(node, "update", _("available")) self.modulesView.set(node, "descr", moduleInfo.get("description")) self.modulesView.set(node, "license", moduleInfo.get("license")) if moduleInfo.get("imports"): loadSubtree(node, [(importModuleInfo["name"],importModuleInfo) for importModuleInfo in moduleInfo["imports"]]) loadSubtree("", self.pluginConfig.get("modules", {}).items()) # clear previous treeview entries for previousNode in self.classesView.get_children(""): self.classesView.delete(previousNode) for i, classItem in enumerate(sorted(self.pluginConfig.get("classes", {}).items())): className, moduleList = classItem node = self.classesView.insert("", "end", className, text=className) self.classesView.set(node, "modules", ', '.join(moduleList)) self.moduleSelect() # clear out prior selection def ok(self, event=None): if self.pluginConfigChanged: PluginManager.pluginConfig = self.pluginConfig PluginManager.pluginConfigChanged = True PluginManager.reset() # force reloading of modules if self.uiClassMethodsChanged or self.modelClassesChanged or self.disclosureSystemTypesChanged or self.hostSystemFeaturesChanged: # may require reloading UI affectedItems = "" if self.uiClassMethodsChanged: affectedItems += _("menus of the user interface") if self.modelClassesChanged: if affectedItems: affectedItems += _(" and ") affectedItems += _("model objects of the processor") if self.disclosureSystemTypesChanged: if affectedItems: affectedItems += _(" and ") affectedItems += _("disclosure system types") if self.hostSystemFeaturesChanged: if affectedItems: affectedItems += _(" and ") affectedItems += _("host system features") if messagebox.askyesno(_("User interface plug-in change"), _("A change in plug-in class methods may have affected {0}. " "Please restart Arelle to due to these changes. \n\n" "Should Arelle restart itself now " "(if there are any unsaved changes they would be lost!)?" ).format(affectedItems), parent=self): self.cntlr.uiThreadQueue.put((self.cntlr.quit, [None, True])) self.close() def close(self, event=None): self.parent.focus_set() self.destroy() def moduleSelect(self, *args): node = (self.modulesView.selection() or (None,))[0] if node: node = node.rpartition(GROUPSEP)[2] # drop leading path names for module name moduleInfo = self.pluginConfig.get("modules", {}).get(node) if moduleInfo: self.selectedModule = node name = moduleInfo["name"] self.moduleNameLabel.config(text=name) self.moduleAuthorHdr.config(state=ACTIVE) self.moduleAuthorLabel.config(text=moduleInfo["author"]) self.moduleDescrHdr.config(state=ACTIVE) self.moduleDescrLabel.config(text=moduleInfo["description"]) self.moduleClassesHdr.config(state=ACTIVE) self.moduleClassesLabel.config(text=', '.join(moduleInfo["classMethods"])) self.moduleUrlHdr.config(state=ACTIVE) self.moduleUrlLabel.config(text=moduleInfo["moduleURL"]) self.moduleDateHdr.config(state=ACTIVE) self.moduleDateLabel.config(text=moduleInfo["fileDate"] + " " + (_("(an update is available)") if name in self.modulesWithNewerFileDates else "")) self.moduleLicenseHdr.config(state=ACTIVE) self.moduleLicenseLabel.config(text=moduleInfo["license"]) if moduleInfo.get("imports"): self.moduleImportsHdr.config(state=ACTIVE) _text = ", ".join(mi["name"] for mi in moduleInfo["imports"][:3]) if len(moduleInfo["imports"]) >= 3: _text += ", ..." self.moduleImportsLabel.config(text=_text) _buttonState = DISABLED if moduleInfo.get("isImported") else ACTIVE self.moduleEnableButton.config(state=_buttonState, text={"enabled":self.DISABLE, "disabled":self.ENABLE}[moduleInfo["status"]]) self.moduleReloadButton.config(state=_buttonState) self.moduleRemoveButton.config(state=_buttonState) else: self.selectedModule = None self.moduleNameLabel.config(text="") self.moduleAuthorHdr.config(state=DISABLED) self.moduleAuthorLabel.config(text="") self.moduleDescrHdr.config(state=DISABLED) self.moduleDescrLabel.config(text="") self.moduleClassesHdr.config(state=DISABLED) self.moduleClassesLabel.config(text="") self.moduleUrlHdr.config(state=DISABLED) self.moduleUrlLabel.config(text="") self.moduleDateHdr.config(state=DISABLED) self.moduleDateLabel.config(text="") self.moduleLicenseHdr.config(state=DISABLED) self.moduleLicenseLabel.config(text="") self.moduleImportsHdr.config(state=DISABLED) self.moduleImportsLabel.config(text="") self.moduleEnableButton.config(state=DISABLED, text=self.ENABLE) self.moduleReloadButton.config(state=DISABLED) self.moduleRemoveButton.config(state=DISABLED) def findLocally(self): initialdir = self.cntlr.pluginDir # default plugin directory if not self.cntlr.isMac: # can't navigate within app easily, always start in default directory initialdir = self.cntlr.config.setdefault("pluginOpenDir", initialdir) filename = self.cntlr.uiFileDialog("open", parent=self, title=_("Choose plug-in module file"), initialdir=initialdir, filetypes=[(_("Python files"), "*.py")], defaultextension=".py") if filename: # check if a package is selected (any file in a directory containing an __init__.py #if (os.path.basename(filename) == "__init__.py" and os.path.isdir(os.path.dirname(filename)) and # os.path.isfile(filename)): # filename = os.path.dirname(filename) # refer to the package instead self.cntlr.config["pluginOpenDir"] = os.path.dirname(filename) moduleInfo = PluginManager.moduleModuleInfo(filename) self.loadFoundModuleInfo(moduleInfo, filename) def findOnWeb(self): url = DialogURL.askURL(self) if url: # url is the in-cache or local file moduleInfo = PluginManager.moduleModuleInfo(url) self.cntlr.showStatus("") # clear web loading status self.loadFoundModuleInfo(moduleInfo, url) def loadFoundModuleInfo(self, moduleInfo, url): if moduleInfo and moduleInfo.get("name"): self.addPluginConfigModuleInfo(moduleInfo) self.loadTreeViews() else: messagebox.showwarning(_("Module is not itself a plug-in or in a directory with package __init__.py plug-in. "), _("File does not itself contain a python program with an appropriate __pluginInfo__ declaration: \n\n{0}") .format(url), parent=self) def checkIfImported(self, moduleInfo): if moduleInfo.get("isImported"): messagebox.showwarning(_("Plug-in is imported by a parent plug-in. "), _("Plug-in has a parent, please request operation on the parent: \n\n{0}") .format(moduleInfo.get("name")), parent=self) return True return False def removePluginConfigModuleInfo(self, name): moduleInfo = self.pluginConfig["modules"].get(name) if moduleInfo: if self.checkIfImported(moduleInfo): return; def _removePluginConfigModuleInfo(moduleInfo): _name = moduleInfo.get("name") if _name: for classMethod in moduleInfo["classMethods"]: classMethods = self.pluginConfig["classes"].get(classMethod) if classMethods and _name in classMethods: classMethods.remove(_name) if not classMethods: # list has become unused del self.pluginConfig["classes"][classMethod] # remove class if classMethod.startswith("CntlrWinMain.Menu"): self.uiClassMethodsChanged = True # may require reloading UI elif classMethod == "ModelObjectFactory.ElementSubstitutionClasses": self.modelClassesChanged = True # model object factor classes changed elif classMethod == "DisclosureSystem.Types": self.disclosureSystemTypesChanged = True # disclosure system types changed elif classMethod.startswith("Proxy."): self.hostSystemFeaturesChanged = True # system features (e.g., proxy) changed for importModuleInfo in moduleInfo.get("imports", EMPTYLIST): _removePluginConfigModuleInfo(importModuleInfo) self.pluginConfig["modules"].pop(_name, None) _removePluginConfigModuleInfo(moduleInfo) self.pluginConfigChanged = True def addPluginConfigModuleInfo(self, moduleInfo): if self.checkIfImported(moduleInfo): return; name = moduleInfo.get("name") self.removePluginConfigModuleInfo(name) # remove any prior entry for this module def _addPlugin(moduleInfo): _name = moduleInfo.get("name") if _name: self.modulesWithNewerFileDates.discard(_name) # no longer has an update available self.pluginConfig["modules"][_name] = moduleInfo # add classes for classMethod in moduleInfo["classMethods"]: classMethods = self.pluginConfig["classes"].setdefault(classMethod, []) if name not in classMethods: classMethods.append(_name) if classMethod.startswith("CntlrWinMain.Menu"): self.uiClassMethodsChanged = True # may require reloading UI elif classMethod == "ModelObjectFactory.ElementSubstitutionClasses": self.modelClassesChanged = True # model object factor classes changed elif classMethod == "DisclosureSystem.Types": self.disclosureSystemTypesChanged = True # disclosure system types changed elif classMethod.startswith("Proxy."): self.hostSystemFeaturesChanged = True # system features (e.g., proxy) changed for importModuleInfo in moduleInfo.get("imports", EMPTYLIST): _addPlugin(importModuleInfo) _addPlugin(moduleInfo) self.pluginConfigChanged = True def moduleEnable(self): if self.selectedModule in self.pluginConfig["modules"]: moduleInfo = self.pluginConfig["modules"][self.selectedModule] if self.checkIfImported(moduleInfo): return; def _moduleEnable(moduleInfo): if self.moduleEnableButton['text'] == self.ENABLE: moduleInfo["status"] = "enabled" elif self.moduleEnableButton['text'] == self.DISABLE: moduleInfo["status"] = "disabled" for importModuleInfo in moduleInfo.get("imports", EMPTYLIST): _moduleEnable(importModuleInfo) _moduleEnable(moduleInfo) if self.moduleEnableButton['text'] == self.ENABLE: self.moduleEnableButton['text'] = self.DISABLE elif self.moduleEnableButton['text'] == self.DISABLE: self.moduleEnableButton['text'] = self.ENABLE self.pluginConfigChanged = True self.loadTreeViews() def moduleReload(self): if self.selectedModule in self.pluginConfig["modules"]: url = self.pluginConfig["modules"][self.selectedModule].get("moduleURL") if url: moduleInfo = PluginManager.moduleModuleInfo(url, reload=True) if moduleInfo: if self.checkIfImported(moduleInfo): return; self.addPluginConfigModuleInfo(moduleInfo) self.loadTreeViews() self.cntlr.showStatus(_("{0} reloaded").format(moduleInfo["name"]), clearAfter=5000) else: messagebox.showwarning(_("Module error"), _("File or module cannot be reloaded: \n\n{0}") .format(url), parent=self) def moduleRemove(self): if self.selectedModule in self.pluginConfig["modules"]: self.removePluginConfigModuleInfo(self.selectedModule) self.pluginConfigChanged = True self.loadTreeViews() def enableAll(self): self.enableDisableAll(True) def disableAll(self): self.enableDisableAll(False) def enableDisableAll(self, doEnable): for module in self.pluginConfig["modules"]: if not module.get("isImported"): moduleInfo = self.pluginConfig["modules"][module] def _enableDisableAll(moduleInfo): if doEnable: moduleInfo["status"] = "enabled" else: moduleInfo["status"] = "disabled" for importModuleInfo in moduleInfo.get("imports", EMPTYLIST): _enableDisableAll(importModuleInfo) _enableDisableAll(moduleInfo) if doEnable: self.moduleEnableButton['text'] = self.DISABLE else: self.moduleEnableButton['text'] = self.ENABLE self.pluginConfigChanged = True self.loadTreeViews()