class app(): def __init__(self): self.window = Tk() self.window.geometry('500x500') self.window.title('LIBRUSReader') loginLabel = Label(text='Podaj login') passwordLabel = Label(text='Podaj hasło') loginLabel.place(x=10, y=25) passwordLabel.place(x=10, y=50) self.login = StringVar() self.password = StringVar() self.windowMode = BooleanVar() self.consoleReadingMessages = BooleanVar() self.answer = StringVar() loginEntry = Entry(textvariable=self.login, width='30') passwordEntry = Entry(textvariable=self.password, show='*', width='30') loginEntry.place(x=80, y=25) passwordEntry.place(x=80, y=50) checkbox = Checkbutton(self.window, text='Tryb okienkowy', variable=self.windowMode) checkbox.place(x=15, y=125) checkboxOdczyt = Checkbutton( self.window, text= 'Wyświetlanie wiadomości w konsoli (użyteczne przy wyłączeniu trybu okienkowego', variable=self.consoleReadingMessages) checkboxOdczyt.place(x=15, y=150) self.answer = Text(self.window, width='54', height='15') answerLabel = Label( text='Odpowiedź do wiadomości (jeśli puste, nie przesyła)') self.answer.place(x=15, y=215) answerLabel.place(x=15, y=190) runProgram = Button(self.window, text='Uruchom program', width='36', height=' 1', command=self.zapiszDane, bg='grey') runProgram.place(x=16, y=100) self.window.mainloop() def zapiszDane(self): data = { 'login': self.login.get(), 'password': self.password.get(), 'windowMode': self.windowMode.get(), 'consoleReadingMessages': self.consoleReadingMessages.get(), 'answer': self.answer.get('1.0', 'end-1c') } with open('config.json', 'w') as f: json.dump(data, f) self.window.destroy()
def generate_color_fading_input(): interface = InterfaceInfo.get_instance() interface.reset_parameters() ttk.Label(interface.buttons_frame, text="Image width", background=constants.TOP_COLOR).grid(row=0, column=0) ttk.Label(interface.buttons_frame, text="Image height", background=constants.TOP_COLOR).grid(row=1, column=0) red = BooleanVar() green = BooleanVar() blue = BooleanVar() Checkbutton(interface.buttons_frame, text="Red", variable=red, background=constants.TOP_COLOR).grid(row=2, column=0) Checkbutton(interface.buttons_frame, text="Green", variable=green, background=constants.TOP_COLOR).grid(row=2, column=1) Checkbutton(interface.buttons_frame, text="Blue", variable=blue, background=constants.TOP_COLOR).grid(row=2, column=2) image_width = Entry(interface.buttons_frame) image_height = Entry(interface.buttons_frame) image_width.grid(row=0, column=1) image_height.grid(row=1, column=1) generate_gray_fading_button = ttk.Button( interface.buttons_frame, text="Show", command=lambda: color_faded_image(int(image_width.get( )), int(image_height.get()), red.get(), green.get(), blue.get())) generate_gray_fading_button.grid(row=3, column=0)
def test_invalid_value_domain(self): v = BooleanVar(self.root, name="name") self.root.globalsetvar("name", "value") with self.assertRaises(ValueError): v.get() self.root.globalsetvar("name", "1.0") with self.assertRaises(ValueError): v.get()
def service_clicked(self, name: str, var: tk.BooleanVar) -> None: if var.get() and name not in self.current_services: self.current_services.add(name) elif not var.get() and name in self.current_services: self.current_services.remove(name) self.current.listbox.delete(0, tk.END) for name in sorted(self.current_services): self.current.listbox.insert(tk.END, name)
def test_get(self): v = BooleanVar(self.root, True, "name") self.assertIs(v.get(), True) self.root.globalsetvar("name", "0") self.assertIs(v.get(), False) self.root.globalsetvar("name", 42 if self.root.wantobjects() else 1) self.assertIs(v.get(), True) self.root.globalsetvar("name", 0) self.assertIs(v.get(), False) self.root.globalsetvar("name", "on") self.assertIs(v.get(), True)
def test_get(self): v = BooleanVar(self.root, True, 'name') self.assertIs(v.get(), True) self.root.globalsetvar('name', '0') self.assertIs(v.get(), False) self.root.globalsetvar('name', 42 if self.root.wantobjects() else 1) self.assertIs(v.get(), True) self.root.globalsetvar('name', 0) self.assertIs(v.get(), False) self.root.globalsetvar('name', 'on') self.assertIs(v.get(), True)
def test_invalid_value_domain(self): false = 0 if self.root.wantobjects() else "0" v = BooleanVar(self.root, name="name") with self.assertRaises(TclError): v.set("value") self.assertEqual(self.root.globalgetvar("name"), false) self.root.globalsetvar("name", "value") with self.assertRaises(ValueError): v.get() self.root.globalsetvar("name", "1.0") with self.assertRaises(ValueError): v.get()
def test_invalid_value_domain(self): false = 0 if self.root.wantobjects() else '0' v = BooleanVar(self.root, name='name') with self.assertRaises(TclError): v.set('value') self.assertEqual(self.root.globalgetvar('name'), false) self.root.globalsetvar('name', 'value') with self.assertRaises(ValueError): v.get() self.root.globalsetvar('name', '1.0') with self.assertRaises(ValueError): v.get()
class Preferences(Frame): def __init__(self, client): # Basic setup super(Preferences, self).__init__() self.client = client # Setup the variables used self.echo_input = BooleanVar() self.echo_input.set(self.client.config['UI'].getboolean('echo_input')) self.echo_input.trace("w", self.echo_handler) self.logging = BooleanVar() self.logging.set( self.client.config['logging'].getboolean('log_session')) self.logging.trace('w', self.logging_handler) self.log_dir = self.client.config['logging']['log_directory'] # Build the actual window and widgets prefs = Toplevel(self) prefs.wm_title("Preferences") echo_input_label = Label(prefs, text="Echo Input:") logging_label = Label(prefs, text='Log to file:') echo_checkbox = Checkbutton(prefs, variable=self.echo_input) logging_checkbox = Checkbutton(prefs, variable=self.logging) logging_button_text = 'Choose file...' if self.log_dir == "" else self.log_dir logging_button = Button(prefs, text=logging_button_text, command=self.logging_pick_location) # Pack 'em in. echo_input_label.grid(row=0, column=0) echo_checkbox.grid(row=0, column=1) logging_label.grid(row=1, column=0) logging_checkbox.grid(row=1, column=1) logging_button.grid(row=1, column=2) def logging_pick_location(self): location = askdirectory(initialdir="%UserProfile%\Documents\\") self.client.config['logging']['log_directory'] = location self.write_config() def echo_handler(self, arg1, arg2, mode): pprint(self.echo_input.get()) self.client.config['UI']['echo_input'] = 'yes' if self.echo_input.get( ) else 'no' self.write_config() def logging_handler(self, arg1, arg2, mode): self.client.config['logging'][ 'log_session'] = 'yes' if self.logging.get else 'no' self.write_config() def write_config(self, file='config.ini'): self.client.config.write(open(file, 'w'))
class Preferences(Frame): def __init__(self, client): # Basic setup super(Preferences, self).__init__() self.client = client # Setup the variables used self.echo_input = BooleanVar() self.echo_input.set(self.client.config['UI'].getboolean('echo_input')) self.echo_input.trace("w", self.echo_handler) self.logging = BooleanVar() self.logging.set(self.client.config['logging'].getboolean('log_session')) self.logging.trace('w', self.logging_handler) self.log_dir = self.client.config['logging']['log_directory'] # Build the actual window and widgets prefs = Toplevel(self) prefs.wm_title("Preferences") echo_input_label = Label(prefs, text="Echo Input:") logging_label = Label(prefs, text='Log to file:') echo_checkbox = Checkbutton(prefs, variable=self.echo_input) logging_checkbox = Checkbutton(prefs, variable=self.logging) logging_button_text = 'Choose file...' if self.log_dir == "" else self.log_dir logging_button = Button(prefs, text=logging_button_text, command=self.logging_pick_location) # Pack 'em in. echo_input_label.grid(row=0, column=0) echo_checkbox.grid(row=0, column=1) logging_label.grid(row=1, column=0) logging_checkbox.grid(row=1, column=1) logging_button.grid(row=1, column=2) def logging_pick_location(self): location = askdirectory(initialdir="%UserProfile%\Documents\\") self.client.config['logging']['log_directory'] = location self.write_config() def echo_handler(self, arg1, arg2, mode): pprint(self.echo_input.get()) self.client.config['UI']['echo_input'] = 'yes' if self.echo_input.get() else 'no' self.write_config() def logging_handler(self, arg1, arg2, mode): self.client.config['logging']['log_session'] = 'yes' if self.logging.get else 'no' self.write_config() def write_config(self, file='config.ini'): self.client.config.write(open(file, 'w'))
class Application(Frame): '''GUI app that allows to choose your favorite genres all-in-ones!''' def __init__(self, master): '''Frame initiation''' super(Application, self).__init__(master) self.grid() self.create_widgets() def create_widgets(self): """Elements that will help to choose""" # Label with description Label( self, text="Choose everything you like:", ).grid(row=1, column=0, sticky=W) # comedy flag self.likes_comedy = BooleanVar() Checkbutton(self, text="Comedy", variable=self.likes_comedy, command=self.update_text).grid(row=2, column=0, sticky=W) # drama flag self.likes_drama = BooleanVar() Checkbutton(self, text="Drama", variable=self.likes_drama, command=self.update_text).grid(row=3, column=0, sticky=W) # action flag self.likes_action = BooleanVar() Checkbutton(self, text="Action", variable=self.likes_action, command=self.update_text).grid(row=4, column=0, sticky=W) # text area with results self.results_txt = Text(self, width=40, height=5, wrap=WORD) self.results_txt.grid(row=5, column=0, columnspan=3) def update_text(self): '''refreshes text area while user changes his preferences''' likes = "" if self.likes_comedy.get(): likes += "You like comedies.\n" if self.likes_drama.get(): likes += "You like drama.\n" if self.likes_action.get(): likes += "You like action.\n" self.results_txt.delete(0.0, END) self.results_txt.insert(0.0, likes)
class KRCCModule: __metaclass__ = ABCMeta def __init__(self): self._terminate = BooleanVar(False) self._id = StringVar(False) @property def terminate(self): return self._terminate.get() @terminate.setter def terminate(self, value): self._terminate.set(value) @property def id(self): return self._id.get() @id.setter def id(self, value): self._id.set(value) @abstractproperty def name(self): pass @abstractmethod def run(self): pass
class Example(Frame): def __init__(self): super().__init__() self.initUI() def initUI(self): self.master.title("Checkbutton") self.pack(fill=BOTH, expand=True) self.var = BooleanVar() cb = Checkbutton(self, text="Show title", variable=self.var, command=self.onClick) cb.select() cb.place(x=50, y=50) def onClick(self): if self.var.get() == True: self.master.title("Checkbutton") else: self.master.title("")
class Exemple(Frame): def __init__(self): super().__init__() self.initUI() def initUI(self): self.style = Style() self.style.theme_use("default") self.master.title("convertisseur") self.pack(fill = BOTH, expand = 1) frame = Frame(self, relief = RAISED, borderwidth = 1) frame.pack(fill = BOTH, expand = True) bouton = Button(self, text = "Quit", command = self.quit) bouton.pack(side = RIGHT, padx = 5, pady = 5) bouton1 = Button(self, text = "stay") bouton1.pack(side = RIGHT, padx = 5, pady = 5) self.var = BooleanVar() cb = Checkbutton(self, text = "Montre le titre", variable = self.var, command = self.onClick) self.var.set(True) cb.pack(side = LEFT, padx = 5, pady = 5) def onClick(self): if self.var.get() == True: self.master.title("convertisseur") else: self.master.title("")
class CheckBox: def __init__(self, root, text: str, x: int, y: int): self.varChecked = BooleanVar() self.text = text self.checkbox = Checkbutton(root, text=self.text, variable=self.varChecked, onvalue=True, offvalue=False) self.x = x self.y = y self.checkbox.pack() self.checkbox.place(x=self.x, y=self.y) @property def command(self): return self.command @command.setter def command(self, command): self.checkbox['command'] = command def isChecked(self): return True if self.varChecked.get() else False def check(self): self.checkbox.select() def uncheck(self): self.checkbox.deselect()
def mac_auto(is_auto: tk.BooleanVar, entry: ttk.Entry, mac: tk.StringVar) -> None: if is_auto.get(): mac.set("") entry.config(state=tk.DISABLED) else: mac.set("00:00:00:00:00:00") entry.config(state=tk.NORMAL)
class SettingsWindow(Toplevel): def __init__(self) -> None: Toplevel.__init__(self) self.title("Settings") #self.geometry("300x180") self.config = configparser.ConfigParser() self.config.read('config.ini') self.val_int_cmd = (self.register(vcmdtk.test_int), '%d', '%S') self.create_gui() self.load_settings() self.grid_gui() def create_gui(self): #Label self.y_max_label = Label(self, text='Y max') self.y_min_label = Label(self, text='Y min') #Entry self.y_max_entry = Entry(self, validate='key', validatecommand=self.val_int_cmd) self.y_min_entry = Entry(self, validate='key', validatecommand=self.val_int_cmd) #Check buttons self.check_var_1 = BooleanVar() self.check_var_1.set( self.config.getboolean('Y Limits', 'use_auto_values')) self.auto_y_cbutton = Checkbutton(self, text='Use auto Y-value ranges', variable=self.check_var_1, command=self.auto_y) #buttons self.ok_button = Button(self, text='Ok', command=self.ok_command) self.cancel_button = Button(self, text='Cancel', command=self.destroy) def grid_gui(self): self.y_max_label.grid(row=0, column=0, pady=2) self.y_min_label.grid(row=1, column=0, pady=2) self.y_max_entry.grid(row=0, column=1, pady=2) self.y_min_entry.grid(row=1, column=1, pady=2) self.auto_y_cbutton.grid(row=0, column=2, columnspan=2, sticky=W) self.ok_button.grid(row=2, column=2) self.cancel_button.grid(row=2, column=3) def auto_y(self): '''configures values afor check button''' if self.check_var_1.get(): #if checked state = 'disabled' else: state = 'enabled' self.y_max_entry['state'] = state self.y_min_entry['state'] = state def load_settings( self): #Inserts settings values(if not none) to tk.entry widghets if (x := self.config['Y Limits']['y_max']) != 'None': self.y_max_entry.insert(0, x) if (x := self.config['Y Limits']['y_min']) != 'None': self.y_min_entry.insert(0, x)
def generate_circle_input(): interface = InterfaceInfo.get_instance() interface.clean_images() interface.delete_widgets(interface.buttons_frame) interface.delete_widgets(interface.image_frame) ttk.Label(interface.buttons_frame, text="Radius", background=constants.TOP_COLOR).grid(row=0, column=2) ttk.Label(interface.buttons_frame, text="Image width", background=constants.TOP_COLOR).grid(row=0, column=0) ttk.Label(interface.buttons_frame, text="Image height", background=constants.TOP_COLOR).grid(row=1, column=0) radius = Entry(interface.buttons_frame) image_width = Entry(interface.buttons_frame) image_height = Entry(interface.buttons_frame) radio_var = BooleanVar() radio_var.set(True) Radiobutton(interface.buttons_frame, text="Filled", value=True, variable=radio_var, background=constants.TOP_COLOR).grid(row=0, column=4) Radiobutton(interface.buttons_frame, text="Empty", value=False, variable=radio_var, background=constants.TOP_COLOR).grid(row=1, column=4) radius.grid(row=0, column=3) image_width.grid(row=0, column=1) image_height.grid(row=1, column=1) draw_pixel_button = ttk.Button(interface.buttons_frame, text="Draw", command=lambda:generate_circle("circle.png", int(image_width.get()), int(image_height.get()), int(radius.get()), radio_var.get())) # Todo validate params draw_pixel_button.grid(row=3, column=0)
class OBCheckbutton(Tk): """ Messagebox with only one button and a checkbox below the button for instance to add a 'Do not show this again' option """ def __init__(self, title="", message="", button="Ok", image=None, checkmessage="", **options): """ Create a messagebox with one button and a checkbox below the button: parent: parent of the toplevel window title: message box title message: message box text button: message displayed on the button image: image displayed at the left of the message checkmessage: message displayed next to the checkbox **options: other options to pass to the Toplevel.__init__ method """ Tk.__init__(self, **options) self.title(title) self.resizable(False, False) self.columnconfigure(1, weight=1) self.rowconfigure(0, weight=1) style = Style(self) style.theme_use(STYLE) self.img = None if isinstance(image, str): try: self.img = PhotoImage(file=image) except TclError: self.img = PhotoImage(data=image) elif image: self.img = image if self.img: Label(self, image=self.img).grid(row=0, column=0, padx=10, pady=(10, 0)) Label(self, text=message, wraplength=335, font="TkDefaultFont 10 bold").grid(row=0, column=1, padx=10, pady=(10, 0)) b = Button(self, text=button, command=self.destroy) b.grid(row=2, padx=10, pady=10, columnspan=2) self.var = BooleanVar(self) c = Checkbutton(self, text=checkmessage, variable=self.var) c.grid(row=1, padx=10, pady=4, sticky="e", columnspan=2) self.grab_set() b.focus_set() def get_check(self): return self.var.get()
def toggle_column(self, variable: tk.BooleanVar, index: int, column: str): columns = list(self.parent.widget_treeview["displaycolumns"]) if variable.get(): columns.insert(index, column) # print("Added '{}' to the shown columns.".format(column)) else: columns.pop(columns.index(column)) # print("Removed '{}' from the shown columns.".format(column)) self.parent.widget_treeview["displaycolumns"] = columns = tuple( columns)
def mac_auto(is_auto: tk.BooleanVar, entry: ttk.Entry): logging.info("mac auto clicked") if is_auto.get(): logging.info("disabling mac") entry.delete(0, tk.END) entry.insert(tk.END, "") entry.config(state=tk.DISABLED) else: entry.delete(0, tk.END) entry.insert(tk.END, "00:00:00:00:00:00") entry.config(state=tk.NORMAL)
class RootFrame(Frame): def __init__(self, master): Frame.__init__(self, master) self._value = os.getcwd() self._var = StringVar(self) self._var.set(self._value) self._var.trace('w', self._validate) label = Label(self, text="Root:") label.pack(side=LEFT) self._entry = Entry(self, textvariable=self._var) self._entry.pack(side=LEFT, fill=X, expand=True) self._recursive_var = BooleanVar() recursive_cb = Checkbutton(self, text='Recursive', variable=self._recursive_var) recursive_cb.pack(side=LEFT) self._recursive_var.trace('w', self._validate) open_button = Button(self, text="Open", command=self._select_root) open_button.pack(side=LEFT) refresh_button = Button(self, text="Refresh", command=self._refresh) refresh_button.pack(side=LEFT) repad(self, 'padx', 0, 5) def _refresh(self): self.event_generate('<<Refresh>>', when='tail') def _validate(self, *_): res = self._var.get().strip() if os.path.isdir(res): self._entry.config(fg='black') self._value = res else: self._entry.config(fg='red') self._value = None self.event_generate('<<RootUpdate>>', when='tail') def _select_root(self): value = askdirectory() if value: self._var.set(value) self._validate() @property def root(self): return self._value @property def recursive(self): return self._recursive_var.get()
class Boolean(Editor): def __init__(self, master, style_def=None): super().__init__(master, style_def) self.config(**self.style.dark, **self.style.dark_highlight_active) self._var = BooleanVar() self._var.trace('w', self.check_change) self._check = Checkbutton(self, text='') self._check['variable'] = self._var self._check.pack(fill="x") def check_change(self, *_): self._check.config(text=str(self._var.get())) if self._on_change is not None: self._on_change(self._var.get()) def set(self, value): self._var.set(bool(value)) self._check.config(text=str(self._var.get())) def get(self): return bool(self._var.get())
class Dots(Tk): def __init__(self): super().__init__() self.w = Canvas(self, bg='#aaa') self.d = [] self.t = Thread(target=self.physics, daemon=True) self.g = .04 self.closing = False self.start = BooleanVar(self) self.w.pack() self.w.bind('<Button-1>', lambda ev: self.new(ev.x, ev.y)) self.bind('<space>', lambda ev: self.start.set(not self.start.get())) self.protocol('WM_DELETE_WINDOW', self.on_close) self.t.start() def on_close(self): self.closing = True self.destroy() def new(self, x, y): self.d += [Dot(x, y)] def physics(self): try: while not self.closing: if self.d: x = sum([e.x for e in self.d]) / len(self.d) y = sum([e.y for e in self.d]) / len(self.d) self.w.delete(ALL) for e in self.d: if self.start.get(): e.vx += self.g * (x - e.x) e.vy += self.g * (y - e.y) e.update() e.render(self.w) sleep(1 / 20) except: if not self.closing: raise
class Application(Frame): "application frame" def __init__(self, master): """ @ brief initialize the frame with master @ params self -- new instance master -- root container """ super(Application, self).__init__(master) self.grid() self.__createWidgets() def __createWidgets(self): """ @ brief create the widgets """ Label(self, text="input dictionary tree: ") \ .grid(row=0, column=0, sticky=W) self.dict_with_label = BooleanVar() Checkbutton(self, text="label edge", variable=self.dict_with_label) \ .grid(row=0, column=0, sticky=E) self.source_text = Text(self, width=40, wrap=WORD) self.source_text.grid(row=1, column=0, sticky=W) Button(self, text="visual tree", command=self.__submitSource) \ .grid(row=2, column=0, sticky=W) Button(self, text="clear", command=self.__clearText) \ .grid(row=2, column=0, sticky=E) def __submitSource(self): "listener for visual button" source = self.source_text.get("1.0", END) if "" != source: current_view = Draw(self) current_view.initDot() current_view.setSource(source, self.dict_with_label.get()) current_view.show() def __clearText(self): "clear button callback" self.source_text.delete(0.0, END)
def popup_settings() -> None: """Открывает окно 'Настройки'.""" popup = Toplevel() log_var = BooleanVar() launchicon = PhotoImage(file = 'data/imgs/20ok.png') center_x_pos = int(popup.winfo_screenwidth() / 2) - POPUP_WIDTH center_y_pos = int(popup.winfo_screenheight() / 2) - POPUP_HEIGHT popup.geometry(f'{POPUP_WIDTH}x{POPUP_HEIGHT}+' f'{center_x_pos}+{center_y_pos}') popup.title(_('Settings')) popup.resizable(False, False) frame_settings = LabelFrame(popup, text = _('Settings')) frame_settings.grid(sticky = 'NWSE', column = 0, row = 0, ipadx = 5, padx = 5, pady = 5) lang_label = Label(frame_settings, text = _('Localisation')) lang_label.grid(column = 0, row = 0, ipadx = 5) logs_label = Label(frame_settings, text = _('Logging')) logs_label.grid(column = 0, row = 1, ipadx = 5) lang_vars = Combobox(frame_settings, state = 'readonly', values = check_langs(), width = 4) lang_vars.current(current_lang()) lang_vars.grid(column = 1, row = 0) log_settings = Checkbutton(frame_settings, variable = log_var, onvalue = True, offvalue = False) log_settings.grid(column = 1, row = 1) if getconfig()['settings']['logging'] == 'True': log_var.set(True) elif getconfig()['settings']['logging'] == 'False': log_var.set(False) apply_button = Button(popup, text = _('Apply'), width = 20, compound = 'left', image = launchicon, command = lambda: apply( lang_vars.get(), popup, log_var.get() ) ) apply_button.grid(column = 0, row = 1) popup.grab_set() popup.focus_set() popup.wait_window()
class CustomRun(Query): """Get settings for custom run of module. 1. Command line arguments to extend sys.argv. 2. Whether to restart Shell or not. """ # Used in runscript.run_custom_event def __init__(self, parent, title, *, cli_args=[], _htest=False, _utest=False): """cli_args is a list of strings. The list is assigned to the default Entry StringVar. The strings are displayed joined by ' ' for display. """ message = 'Command Line Arguments for sys.argv:' super().__init__( parent, title, message, text0=cli_args, _htest=_htest, _utest=_utest) def create_extra(self): "Add run mode on rows 10-12." frame = self.frame self.restartvar = BooleanVar(self, value=True) restart = Checkbutton(frame, variable=self.restartvar, onvalue=True, offvalue=False, text='Restart shell') self.args_error = Label(frame, text=' ', foreground='red', font=self.error_font) restart.grid(column=0, row=10, columnspan=3, padx=5, sticky='w') self.args_error.grid(column=0, row=12, columnspan=3, padx=5, sticky='we') def cli_args_ok(self): "Validity check and parsing for command line arguments." cli_string = self.entry.get().strip() try: cli_args = shlex.split(cli_string, posix=True) except ValueError as err: self.showerror(str(err)) return None return cli_args def entry_ok(self): "Return apparently valid (cli_args, restart) or None." cli_args = self.cli_args_ok() restart = self.restartvar.get() return None if cli_args is None else (cli_args, restart)
class LoginController: def __init__(self, view, user): self.view = view self.user = user self.mail = StringVar() self.password = StringVar() self.checkbox = BooleanVar() self.configControl() def configControl(self): self.view.mail.config(textvariable=self.mail) self.view.password.config(textvariable=self.password) self.view.admin.config(variable=self.checkbox) def valideEmail(self): return self.mail.get() != "" def validePassword(self): return self.password.get() != "" def onButtonValidationClicked(self): if self.valideEmail() and self.validePassword(): self.user.mail = self.mail.get() self.user.password = self.password.get() if self.user.exist(): if self.checkbox.get(): if self.user.isAdmin(): self.user.connect(True) admin = Admin(self.user) self.view.master.connectAdmin(admin) else: messagebox.showerror( title="Bad Entry", message="This admin account does not exist") else: self.user.connect(False) customer = Customer(self.user) self.view.master.connectCustomer(customer) else: messagebox.showerror(title="Bad Entry", message="Error wrong email or password ") else: messagebox.showerror(title="Bad Entry", message="Error wrong email or password ")
class CheckSpin(Frame): def __init__(self, parent, width=200, height=50, val=(0, 100), inc=1, font=('Times', 12), ratio=0.5): Frame.__init__(self, parent, width=width, height=height) self.pack_propagate(0) self.f1 = Frame(self, width=int(width * ratio), height=height) self.f1.pack_propagate(0) self.f1.pack(side='left') self.f2 = Frame(self, width=int(width * (1 - ratio)), height=height) self.f2.pack_propagate(0) self.f2.pack(side='left') self.isfloat = BooleanVar(self.f1) self.limit = val self.rd_f = Checkbutton(self.f1, text="float", font=font, variable=self.isfloat, onvalue=True, offvalue=False) self.rd_f.pack(side='left', fill="y") self.sp = Spinbox(self.f2, font=font, from_=val[0], to=val[1], increment=inc) self.sp.pack(fill='both', expand=True) def get(self): valstr = self.sp.get() try: val = float(valstr) val = self.limit[1] if val > self.limit[1] else val val = self.limit[0] if val < self.limit[0] else val except ValueError: val = 0 return self.isfloat.get(), val
class Location: def __init__(self, master: Frame = None): self.raw_path = StringVar(master) self.path = StringVar(master) self.nas = BooleanVar(master) def set_dir(self): path = askdirectory() self.raw_path.set(path) self.set_nas_dir() def set_nas_dir(self): path = self.raw_path.get() if self.nas.get(): path = remove_prefix(path, "/Volumes") path = (Rsync.base_nas + path).replace("//", "/") self.path.set(path)
class CustomRun(Query): """Get settings for custom run of module. 1. Command line arguments to extend sys.argv. 2. Whether to restart Shell or not. """ # Used in runscript.run_custom_event def __init__(self, parent, title, *, cli_args='', _htest=False, _utest=False): # TODO Use cli_args to pre-populate entry. message = 'Command Line Arguments for sys.argv:' super().__init__( parent, title, message, text0=cli_args, _htest=_htest, _utest=_utest) def create_widgets(self): super().create_widgets(ok_text='Run') frame = self.frame self.restartvar = BooleanVar(self, value=True) restart = Checkbutton(frame, variable=self.restartvar, onvalue=True, offvalue=False, text='Restart shell') self.args_error = Label(frame, text=' ', foreground='red', font=self.error_font) restart.grid(column=0, row=4, columnspan=3, padx=5, sticky='w') self.args_error.grid(column=0, row=12, columnspan=3, padx=5, sticky='we') def cli_args_ok(self): "Validity check and parsing for command line arguments." cli_string = self.entry.get().strip() try: cli_args = shlex.split(cli_string, posix=True) except ValueError as err: self.showerror(str(err)) return None return cli_args def entry_ok(self): "Return apparently valid (cli_args, restart) or None" self.entry_error['text'] = '' cli_args = self.cli_args_ok() restart = self.restartvar.get() return None if cli_args is None else (cli_args, restart)
class Application(Frame): "application frame" def __init__(self, master): """ @ brief initialize the frame with master @ params self -- new instance master -- root container """ super(Application, self).__init__(master) self.grid() self.__createWidgets() def __createWidgets(self): """ @ brief create the widgets """ Label(self, text="input dictionary tree: ").grid(row=0, column=0, sticky=W) self.dict_with_label = BooleanVar() Checkbutton(self, text="label edge", variable=self.dict_with_label).grid(row=0, column=0, sticky=E) self.source_text = Text(self, width=40, wrap=WORD) self.source_text.grid(row=1, column=0, sticky=W) Button(self, text="visual tree", command=self.__submitSource).grid(row=2, column=0, sticky=W) Button(self, text="clear", command=self.__clearText).grid(row=2, column=0, sticky=E) def __submitSource(self): "listener for visual button" source = self.source_text.get("1.0", END) if "" != source: current_view = Draw(self) current_view.initDot() current_view.setSource(source, self.dict_with_label.get()) current_view.show() def __clearText(self): "clear button callback" self.source_text.delete(0.0, END)
class OBCheckbutton(Tk): """ Messagebox with only one button and a checkbox below the button for instance to add a 'Do not show this again' option """ def __init__(self, title="", message="", button="Ok", image=None, checkmessage="", style="clam", **options): """ Create a messagebox with one button and a checkbox below the button: parent: parent of the toplevel window title: message box title message: message box text button: message displayed on the button image: image displayed at the left of the message checkmessage: message displayed next to the checkbox **options: other options to pass to the Toplevel.__init__ method """ Tk.__init__(self, **options) self.resizable(False, False) self.title(title) s = Style(self) s.theme_use(style) if image: Label(self, text=message, wraplength=335, font="Sans 11", compound="left", image=image).grid(row=0, padx=10, pady=(10, 0)) else: Label(self, text=message, wraplength=335, font="Sans 11").grid(row=0, padx=10, pady=(10, 0)) b = Button(self, text=button, command=self.destroy) b.grid(row=2, padx=10, pady=10) self.var = BooleanVar(self) c = Checkbutton(self, text=checkmessage, variable=self.var) c.grid(row=1, padx=10, pady=0, sticky="e") self.grab_set() b.focus_set() self.wait_window(self) def get_check(self): return self.var.get()
def test_default(self): v = BooleanVar(self.root) self.assertEqual(False, v.get())
class dpph_measurement: ''' ''' def __init__(self, pype, toplevel=False, **runargs): ''' ''' self.pype = pype self.runargs = runargs self.toplevel = toplevel self.sweep_result = {} self.powerVar = DoubleVar(value=20) #dBm self.set_power_BoolVar = BooleanVar(value=True) self.start_freq_Var = DoubleVar(value=26350) #MHz self.stop_freq_Var = DoubleVar(value=26600) #MHz self.start_search_freq_Var = DoubleVar(value=26450) #MHz self.stop_search_freq_Var = DoubleVar(value=26510) #MHz self.sweep_time_Var = DoubleVar(value=15) #s self.num_points_Var = IntVar(value=400) #ms self.spanVar = DoubleVar(value=100) self.stepVar = DoubleVar(value=4) #self.fit_channel_Var = StringVar(value='xdata') self.result_str_Var = StringVar(value='') self._BuildGui() def _BuildGui(self): ''' Dpph popup window ''' row = 0 ################################################################## # Lockin Scan Label(self.toplevel, text='Input Power' ).grid(row=row, column=0, sticky='ew') Entry(self.toplevel, textvariable=self.powerVar ).grid(row=row, column=1, sticky='ew') Label(self.toplevel, text='[dBm]', justify='left' ).grid(row=row, column=2, sticky='w') Checkbutton(self.toplevel, text="Don't Change", variable=self.set_power_BoolVar).grid(row=row, column=3) row += 1 Label(self.toplevel, text='Scan Frequency Range' ).grid(row=row, column=0, sticky='ew') Entry(self.toplevel, textvariable=self.start_freq_Var ).grid(row=row, column=1, sticky='ew') Entry(self.toplevel, textvariable=self.stop_freq_Var ).grid(row=row, column=2, columnspan=2, sticky='ew') Label(self.toplevel, text='[MHz]').grid(row=row, column=4, sticky='w') row += 1 Label(self.toplevel, text='Sweep Time' ).grid(row=row, column=0, sticky='ew') Entry(self.toplevel, textvariable=self.sweep_time_Var ).grid(row=row, column=1, sticky='ew') Label(self.toplevel, text='[s]').grid(row=row, column=2, sticky='w') row += 1 Label(self.toplevel, text='Number of Points' ).grid(row=row, column=0, sticky='ew') Entry(self.toplevel, textvariable=self.num_points_Var ).grid(row=row, column=1, sticky='ew') row += 1 Button(self.toplevel, text='take data', command=self._CollectSweep ).grid(row=row, column=0) row += 1 Label(self.toplevel, text='-'*50).grid(row=row, column=0, columnspan=4, sticky='ew') row += 1 ################################################################## # Resonance Search Label(self.toplevel, text='Search Frequency Range' ).grid(row=row, column=0, sticky='ew') Entry(self.toplevel, textvariable=self.start_search_freq_Var ).grid(row=row, column=1, sticky='ew') Entry(self.toplevel, textvariable=self.stop_search_freq_Var ).grid(row=row, column=2, columnspan=2, sticky='ew') Label(self.toplevel, text='[MHz]').grid(row=row, column=4, sticky='w') row += 1 #ch_options = ['xdata', 'ydata'] #OptionMenu(self.toplevel, self.fit_channel_Var, *ch_options # ).grid(row=row, column=0, rowspan=2, sticky='ew') Button(self.toplevel, text='find resonance', command=self._FindResonance ).grid(row=row, column=1, rowspan=2, sticky='ew') Label(self.toplevel, textvariable=self.result_str_Var ).grid(row=row, column=2, rowspan=2, columnspan=3, sticky='ew') row += 2 Button(self.toplevel, text='Dump To json', command=self._SaveJson ).grid(row=row, column=0) Button(self.toplevel, text='Save Image', command=self._SaveFigure ).grid(row=row, column=1) Button(self.toplevel, text='Log DPPH', command=self._LogDPPH ).grid(row=row, column=2) self._SetupPlot(row=0, column=5) def _SetupPlot(self, row, column): ''' Initialize the plot in the gui ''' self.figure = Figure() self.figure.subplots_adjust(left=0.15, bottom=0.2) self.subfigure = self.figure.add_subplot(1, 1, 1) self.subfigure.plot([0], [0]) self.subfigure.plot([0], [0]) self.subfigure.set_xlabel('Freq [MHz]') self.canvas = FigureCanvasTkAgg(self.figure, master=self.toplevel) self.canvas.show() self.canvas.get_tk_widget().grid(row=row, column=column, rowspan=10) def _CollectSweep(self): ''' ''' tmp_power = self.powerVar.get() if self.set_power_BoolVar.get(): tmp_power = False while True: sweep = _GetSweptVoltages(pype=self.pype, start_freq=self.start_freq_Var.get(), stop_freq=self.stop_freq_Var.get(), sweep_time=self.sweep_time_Var.get(), power=tmp_power, num_points=self.num_points_Var.get()) self.sweep_result = sweep.copy() freqdata = array(sweep['frequency_curve']) magdata = sweep['amplitude_curve'] if type(magdata[0]) is unicode: print('Warning: _GetSweptVoltages failed;') print('magdata:') print(magdata) print('Acquiring data again...') elif type(magdata[0]) is int: break if not sweep['frequencies_confirmed']: showwarning('Warning', 'Communication with lockin amp failed. Frequencies data may be wrong') magdata = magdata - mean(magdata) #ydata = sweep['y_curve'] print('freq range is ', min(freqdata), ' to ', max(freqdata)) #xdata = sweep['x_curve'] y_del = max((max(magdata) - min(magdata)) * .05, 1) self.subfigure.set_xlim(left=freqdata[0], right=freqdata[-1]) self.subfigure.set_ylim(bottom=(min(magdata) - y_del), top=(max(magdata) + y_del)) line = self.subfigure.get_lines()[0] line.set_xdata(array(freqdata)) line.set_ydata(array(magdata)) line.set_label('lockin output') #line = self.subfigure.get_lines()[1] #line.set_xdata(array(freqdata)) #line.set_ydata(array(ydata)) #line.set_label('y output') self.figure.legends = [] self.figure.legend(*self.subfigure.get_legend_handles_labels()) self.figure.legends[0].draggable(True) self.canvas.draw() self.canvas.show() print('Searching for resonance...') self._FindResonance() def _FindResonance(self): ''' ''' #if self.fit_channel_Var.get() == 'xdata': # line = self.subfigure.get_lines()[0] #elif self.fit_channel_Var.get() == 'ydata': # line = self.subfigure.get_lines()[1] line = self.subfigure.get_lines()[0] #else: # raise ValueError('not a valid dataset selection') xdata = line.get_xdata() ydata = line.get_ydata() fit = _FindFieldFFT(min_freq=self.start_search_freq_Var.get(), max_freq=self.stop_search_freq_Var.get(), freq_data=xdata, volts_data=ydata) outline = self.subfigure.get_lines()[1] factor = max(ydata) / max(fit['result']) scaled_data = [val * factor for val in fit['result']] scaled_data = scaled_data - mean(scaled_data) outline.set_xdata(fit['freqs']) outline.set_ydata(scaled_data) outline.set_label('filter result') self.figure.legends = [] self.figure.legend(*self.subfigure.get_legend_handles_labels()) self.figure.legends[0].draggable(True) self.canvas.draw() self.canvas.show() res_freq = max(zip(fit['result'], fit['freqs']))[1] res_unct = fit['freqs'][1] - fit['freqs'][0] print('resonance found at:', res_freq, 'MHz') print('err is:', res_unct) geff = 2.0036 chargemass = 1.758e11 freq_to_field = 4 * pi * 10 ** 7 / (geff * chargemass) res_field = freq_to_field * res_freq res_field_unct = freq_to_field * res_unct print('for a field of', res_field) print('field unct of', res_field_unct) self.result_str_Var.set('{:.4E} +/- {:.1E} MHz \n({:.4E} +/- {:.1E} kG)'.format( res_freq, res_unct, res_field, res_field_unct)) self.sweep_result.update({'res_freq': res_freq, 'res_freq_unct': res_unct, 'res_field': res_field, 'res_field_unct': res_field_unct}) def _SaveJson(self): ''' ''' if not self.sweep_result: print('no result stored') return outfile = asksaveasfile(defaultextension='.json') dump(self.sweep_result, outfile, indent=4) outfile.close() def _SaveFigure(self): ''' ''' file_extensions = [('vectorized', '.eps'), ('adobe', '.pdf'), ('image', '.png'), ('all', '.*')] outfile = asksaveasfilename(defaultextension='.pdf', filetypes=file_extensions) self.figure.savefig(outfile) def _LogDPPH(self): if not self.sweep_result: print('no dpph_result stored') return result = { 'uncal': self.sweep_result['res_freq'], 'uncal_err': self.sweep_result['res_freq_unct'], 'uncal_units': 'MHz', 'cal': self.sweep_result['res_field'], 'cal_err': self.sweep_result['res_field_unct'], 'cal_units': 'kG', } dpph_result = {'uncal_val': ' '.join([str(result['uncal']), '+/-', str(result['uncal_err']), result['uncal_units']]), 'cal_val': ' '.join([str(result['cal']), '+/-', str(result['cal_err']), result['cal_units']]), 'timestamp': datetime.utcnow()} self.pype.LogValue(sensor='dpph_field', **dpph_result) print('dpph_result stored')
class SearchEngine: """Handles searching a text widget for Find, Replace, and Grep.""" def __init__(self, root): '''Initialize Variables that save search state. The dialogs bind these to the UI elements present in the dialogs. ''' self.root = root # need for report_error() self.patvar = StringVar(root, '') # search pattern self.revar = BooleanVar(root, False) # regular expression? self.casevar = BooleanVar(root, False) # match case? self.wordvar = BooleanVar(root, False) # match whole word? self.wrapvar = BooleanVar(root, True) # wrap around buffer? self.backvar = BooleanVar(root, False) # search backwards? # Access methods def getpat(self): return self.patvar.get() def setpat(self, pat): self.patvar.set(pat) def isre(self): return self.revar.get() def iscase(self): return self.casevar.get() def isword(self): return self.wordvar.get() def iswrap(self): return self.wrapvar.get() def isback(self): return self.backvar.get() # Higher level access methods def setcookedpat(self, pat): "Set pattern after escaping if re." # called only in SearchDialog.py: 66 if self.isre(): pat = re.escape(pat) self.setpat(pat) def getcookedpat(self): pat = self.getpat() if not self.isre(): # if True, see setcookedpat pat = re.escape(pat) if self.isword(): pat = r"\b%s\b" % pat return pat def getprog(self): "Return compiled cooked search pattern." pat = self.getpat() if not pat: self.report_error(pat, "Empty regular expression") return None pat = self.getcookedpat() flags = 0 if not self.iscase(): flags = flags | re.IGNORECASE try: prog = re.compile(pat, flags) except re.error as what: args = what.args msg = args[0] col = args[1] if len(args) >= 2 else -1 self.report_error(pat, msg, col) return None return prog def report_error(self, pat, msg, col=-1): # Derived class could override this with something fancier msg = "Error: " + str(msg) if pat: msg = msg + "\nPattern: " + str(pat) if col >= 0: msg = msg + "\nOffset: " + str(col) tkMessageBox.showerror("Regular expression error", msg, master=self.root) def search_text(self, text, prog=None, ok=0): '''Return (lineno, matchobj) or None for forward/backward search. This function calls the right function with the right arguments. It directly return the result of that call. Text is a text widget. Prog is a precompiled pattern. The ok parameter is a bit complicated as it has two effects. If there is a selection, the search begin at either end, depending on the direction setting and ok, with ok meaning that the search starts with the selection. Otherwise, search begins at the insert mark. To aid progress, the search functions do not return an empty match at the starting position unless ok is True. ''' if not prog: prog = self.getprog() if not prog: return None # Compilation failed -- stop wrap = self.wrapvar.get() first, last = get_selection(text) if self.isback(): if ok: start = last else: start = first line, col = get_line_col(start) res = self.search_backward(text, prog, line, col, wrap, ok) else: if ok: start = first else: start = last line, col = get_line_col(start) res = self.search_forward(text, prog, line, col, wrap, ok) return res def search_forward(self, text, prog, line, col, wrap, ok=0): wrapped = 0 startline = line chars = text.get("%d.0" % line, "%d.0" % (line+1)) while chars: m = prog.search(chars[:-1], col) if m: if ok or m.end() > col: return line, m line = line + 1 if wrapped and line > startline: break col = 0 ok = 1 chars = text.get("%d.0" % line, "%d.0" % (line+1)) if not chars and wrap: wrapped = 1 wrap = 0 line = 1 chars = text.get("1.0", "2.0") return None def search_backward(self, text, prog, line, col, wrap, ok=0): wrapped = 0 startline = line chars = text.get("%d.0" % line, "%d.0" % (line+1)) while 1: m = search_reverse(prog, chars[:-1], col) if m: if ok or m.start() < col: return line, m line = line - 1 if wrapped and line < startline: break ok = 1 if line <= 0: if not wrap: break wrapped = 1 wrap = 0 pos = text.index("end-1c") line, col = map(int, pos.split(".")) chars = text.get("%d.0" % line, "%d.0" % (line+1)) col = len(chars) - 1 return None
class FrameMapping(FrameCustomItem): """Holds and visualizes a Map between two columns of different datasets""" row_index = None is_key = None src_reference = None src_datatype = None src_cast_to = None dest_table = None curr_data = None curr_raw_data = None mapping = None preview = None dest_reference = None def __init__(self, _master, _mapping = None, _on_get_source_references = None, _on_get_destination_references = None, _on_select = None): super(FrameMapping, self).__init__(_master) # Add monitored variables. self.is_key = BooleanVar() self.src_reference = StringVar() self.src_datatype = StringVar() self.curr_data = StringVar() self.result_cast_to = StringVar() self.preview = StringVar() self.dest_reference = StringVar() self.on_get_source_references = _on_get_source_references self.on_get_destination_references = _on_get_destination_references self.on_select = _on_select self.init_widgets() self.mapping = _mapping if _mapping is not None: self.mapping_to_gui() def mapping_to_gui(self): self.src_reference.set(str(empty_when_none(self.mapping.src_reference))) self.dest_reference.set(str(empty_when_none(self.mapping.dest_reference))) self.src_datatype.set(self.mapping.src_datatype) self.is_key.set(bool_to_binary_int(self.mapping.is_key)) def gui_to_mapping(self): self.mapping.src_reference = self.src_reference.get() self.mapping.dest_reference = self.dest_reference.get() self.mapping.is_key = binary_int_to_bool(self.is_key.get()) def reload_references(self): self.cb_source_ref['values'] = self.get_source_references() self.cb_dest_ref['values'] = self.get_destination_references() def get_source_references(self, _force = None): if self.on_get_source_references: return self.on_get_source_references(_force) def get_destination_references(self, _force = None): if self.on_get_destination_references: return self.on_get_destination_references( _force) def on_change_source_ref(self, *args): # reload dataset. pass def init_widgets(self): """Init all widgets""" # Source reference self.cb_source_ref = ttk.Combobox(self, textvariable=self.src_reference, state='normal') self.cb_source_ref['values'] = self.get_source_references() self.cb_source_ref.pack(side=LEFT, fill=X, expand=1) # Data type label self.l_data_type = ttk.Label(self, textvariable=self.src_datatype, width=8) self.src_datatype.set("Not set") self.l_data_type.pack(side=LEFT) # Dest reference self.cb_dest_ref = ttk.Combobox(self, textvariable=self.dest_reference, state='normal') self.cb_dest_ref['values'] = self.get_destination_references() self.cb_dest_ref.pack(side=RIGHT, fill=X, expand=1) # Is key field self.cb_is_key = ttk.Checkbutton(self, variable=self.is_key) self.cb_is_key.pack(side=RIGHT) # Current data self.l_data = ttk.Label(self, textvariable=self.curr_data) self.curr_data.set("No data") self.l_data.pack(side=RIGHT, fill=X, padx=5)
class take_data: ''' ''' def __init__(self, pype, toplevel=False, filename=False, num_sequences=10, run_tag=''): ''' ''' self.pype = pype self.toplevel = toplevel self.keep_runningVar = BooleanVar(value=True) self.extend_runVar = BooleanVar(value=False) self.run_typeVar = StringVar(value="/tmp/") self.run_tagVar = StringVar(value=run_tag) self.num_sequencesVar = IntVar(value=num_sequences) self.sequence_spacingVar = DoubleVar(value=0) self.len_sequenceVar = DoubleVar() self.stateVar = StringVar(value='done') self.conf_filename = StringVar(value='') self.params = {} self.runthread = multiprocessing.Process() self._GetParamFuncs() if toplevel: self._BuildGui() def _BuildGui(self): ''' Setup all of the buttons and user entries ''' # Data Location row = 0 Label(self.toplevel, text='-'*20+'Data Location'+'-'*20).grid(row=row, columnspan=3, column=0) row += 1 Label(self.toplevel, text='/data').grid(row=row, column=0, sticky='E') run_type_options = ["/tmp/", "/commissioning/", "/runs/"] OptionMenu(self.toplevel, self.run_typeVar, *run_type_options).grid( row=row, column=1, sticky='EW') Entry(self.toplevel, textvariable=self.run_tagVar).grid(row=row, column=2) Checkbutton(self.toplevel, text="Extend if Exists", variable=self.extend_runVar).grid(row=row, column=3) row += 1 Label(self.toplevel, text="(raid location)").grid(row=row, column=0, sticky='E') Label(self.toplevel, text="(run type)").grid(row=row, column=1) Label(self.toplevel, text="(run tag)").grid(row=row, column=2) row += 1 # Acquisition Cycle Details Label(self.toplevel, text='-'*20+'Acquisition Cycles'+'-'*20).grid(row=row, columnspan=3, column=0) row += 1 Label(self.toplevel, text='Number of Sequences').grid(row=row, column=0) Entry(self.toplevel, textvariable=self.num_sequencesVar).grid(row=row, column=1) row += 1 Label(self.toplevel, text='Delay Between').grid(row=row, column=0) Entry(self.toplevel, textvariable=self.sequence_spacingVar).grid(row=row, column=1) Label(self.toplevel, text='[s]').grid(row=row, column=2, sticky='W') row += 1 builtins_list = ['default_run', 'noise_analysis_run'] self.conf_filename.set(builtins_list[0]) Button(self.toplevel, text='Load Builtin Run Def', command=self._GetParamFuncs).grid(row=row, column=0) OptionMenu(self.toplevel, self.conf_filename, *builtins_list).grid( row=row, column=1) self.conf_filename.set(builtins_list[0]) row += 1 Label(self.toplevel, text='Load Custom Run Def').grid(row=row, column=0) Button(self.toplevel, text="find file", command=self._ParamFuncFile ).grid(row=row, column=1) row += 1 # Mantis Settings Label(self.toplevel, text='-'*20+'Mantis Settings'+'-'*20).grid(row=row, columnspan=3, column=0) row += 1 Label(self.toplevel, text='(Empty fields use default values)').grid(row=row, columnspan=3, column=0) row += 1 Label(self.toplevel, text='Digitization Time').grid(row=row, column=0) Entry(self.toplevel, textvariable=self.len_sequenceVar).grid(row=row, column=1) Label(self.toplevel, text='[ms]').grid(row=row, column=2, sticky='W') row += 1 Button(self.toplevel, text="Start Run", command=self.DoRun ).grid(row=row, column=0) Button(self.toplevel, text="ABORT", command=self._Abort, bg='red' ).grid(row=row, column=1) Label(self.toplevel, textvariable=self.stateVar).grid(row=row, column=2) def _ParamFuncFile(self): ''' ''' self.conf_filename.set(askopenfilename()) if self.conf_filename.get(): self._GetParamFuncs() def _Abort(self): ''' ''' self.keep_runningVar.set(False) if self.runthread.is_alive(): print('terminating child process') self.runthread.terminate() else: print('no current thread') self.stateVar.set('aborted') def _IsRunning(self): ''' ''' print(self.runthread.is_alive()) def _GetParamFuncs(self): ''' ''' fname = self.conf_filename.get() if not fname or fname == 'default_run': if not 'run_params' in sys.modules: from . import default_run as run_params else: reload(run_params) elif fname == 'noise_analysis_run': from . import noise_analysis_run as run_params else: imp.load_source('run_params', fname) import run_params self.DefaultParams = run_params.DefaultParams self.SequenceParams = run_params.SequenceParams self.FilenamePrefix = run_params.FilenamePrefix self.Mantis_kwargs = run_params.Mantis_kwargs() if 'duration' in self.Mantis_kwargs: self.len_sequenceVar.set(self.Mantis_kwargs['duration']) def DoRun(self): ''' Execute the run ''' self.keep_runningVar.set(True) self.stateVar.set('normal') if self.runthread.is_alive(): print('there is already live process, abort first or let it finish') else: self.runthread = multiprocessing.Process(target=self.__DoRun) self.runthread.start() def __DoRun(self): ''' the run called by DoRun in a subprocess ''' self.params['run_tag'] = self.run_tagVar.get() self.params['num_sequences'] = self.num_sequencesVar.get() print('setting defaults') self._SetParams(self.DefaultParams()) for sequence_num in range(self.params['num_sequences']): print('--> starting sequence {0}/{1}'.format(sequence_num, self.params['num_sequences'] - 1)) if not self.keep_runningVar.get(): print('Aborting!') break self._DoSequence(sequence_num) print('--> sequence {0}/{1} complete.'.format(sequence_num, self.params['num_sequences'] - 1)) sleep(self.sequence_spacingVar.get()) print('-> run (tag: {0}) complete.'.format(self.params['run_tag'])) self.stateVar.set('run complete') def _SetParams(self, params_list): ''' ''' for channel_name, value in params_list: setattempt = self.pype.Set(channel_name, value) setattempt.Wait() if setattempt.Waiting(): raise NoResponseError('setting ' + str(channel_name)) print(channel_name, '->', value) def _DoSequence(self, sequence_number): ''' Do one sequence within the run ''' mantis_kwargs = self.Mantis_kwargs.copy() run_doc = self.pype.NewDump(uuid4().hex, self.params['run_tag'], new_run=((not sequence_number) and not self.extend_runVar.get())) self._SetParams(self.SequenceParams(sequence_number)) for channel in self.pype.ListWithProperty('dump'): run_doc[channel] = self.pype.Get(channel) run_doc[channel].Update() run_doc[channel].Wait() run_doc._UpdateTo() outfilename = '/data/{:s}_{:05d}_{:05d}.egg'.format( self.FilenamePrefix(sequence_number), run_doc['run_number'], run_doc['sequence_number']) print('outputting '+outfilename) run_descrip = ast.literal_eval(mantis_kwargs['description']) for (chan, val) in self.SequenceParams(sequence_number): run_descrip[chan] = val run_descrip['run_tag'] = self.params['run_tag'] run_doc['sequence_tag'] = dumps(run_descrip) mantis_kwargs.update({'output': outfilename, 'description': dumps(run_descrip), 'duration': self.len_sequenceVar.get()}) run = self.pype.RunMantis(**mantis_kwargs) print('mantis run starting') run.Wait() run_doc['mantis'] = run run_doc._UpdateTo()
def test_default(self): v = BooleanVar(self.root) self.assertIs(v.get(), False)
class GrepDialog(SearchDialogBase): title = "Find in Files Dialog" icon = "Grep" needwrapbutton = 0 def __init__(self, root, engine, flist): SearchDialogBase.__init__(self, root, engine) self.flist = flist self.globvar = StringVar(root) self.recvar = BooleanVar(root) def open(self, text, searchphrase, io=None): SearchDialogBase.open(self, text, searchphrase) if io: path = io.filename or "" else: path = "" dir, base = os.path.split(path) head, tail = os.path.splitext(base) if not tail: tail = ".py" self.globvar.set(os.path.join(dir, "*" + tail)) def create_entries(self): SearchDialogBase.create_entries(self) self.globent = self.make_entry("In files:", self.globvar)[0] def create_other_buttons(self): f = self.make_frame()[0] btn = Checkbutton(f, anchor="w", variable=self.recvar, text="Recurse down subdirectories") btn.pack(side="top", fill="both") btn.select() def create_command_buttons(self): SearchDialogBase.create_command_buttons(self) self.make_button("Search Files", self.default_command, 1) def default_command(self, event=None): prog = self.engine.getprog() if not prog: return path = self.globvar.get() if not path: self.top.bell() return from OutputWindow import OutputWindow # leave here! save = sys.stdout try: sys.stdout = OutputWindow(self.flist) self.grep_it(prog, path) finally: sys.stdout = save def grep_it(self, prog, path): dir, base = os.path.split(path) list = self.findfiles(dir, base, self.recvar.get()) list.sort() self.close() pat = self.engine.getpat() print("Searching %r in %s ..." % (pat, path)) hits = 0 try: for fn in list: try: with open(fn, errors='replace') as f: for lineno, line in enumerate(f, 1): if line[-1:] == '\n': line = line[:-1] if prog.search(line): sys.stdout.write("%s: %s: %s\n" % (fn, lineno, line)) hits += 1 except OSError as msg: print(msg) print(("Hits found: %s\n" "(Hint: right-click to open locations.)" % hits) if hits else "No hits.") except AttributeError: # Tk window has been closed, OutputWindow.text = None, # so in OW.write, OW.text.insert fails. pass def findfiles(self, dir, base, rec): try: names = os.listdir(dir or os.curdir) except OSError as msg: print(msg) return [] list = [] subdirs = [] for name in names: fn = os.path.join(dir, name) if os.path.isdir(fn): subdirs.append(fn) else: if fnmatch.fnmatch(name, base): list.append(fn) if rec: for subdir in subdirs: list.extend(self.findfiles(subdir, base, rec)) return list def close(self, event=None): if self.top: self.top.grab_release() self.top.withdraw()
class OmxGui(Frame): def __init__(self, parent, argv): Frame.__init__(self, parent, padding=(3,6,3,12), style="TFrame") self.parent = parent self.initData() self.initUI() if len(argv) > 1: try: self.updateAndPlayVideo(argv[1]) except FileNotFoundError: self.logDebug('File Not Found') def initData(self): self.browseInitialDir = def_initialDir self.recentFile = def_recentFile self.menuOutputAudio = StringVar() self.menuOutputAudio.set(def_menuOutputAudio) self.menuVideoRefresh = BooleanVar() self.menuVideoRefresh.set(def_menuVideoRefresh) self.menuBgBlack = BooleanVar() self.menuBgBlack.set(def_menuBgBlack) self.maxRecentVideos = def_maxRecentVideos self.moreOptions = def_moreOptions self.playProcess = None def initUI(self): self.parent.title('OMX GUI') self.parent.bind("<Key>", self.keyEvt) # ---- STYLE ---- Style().theme_use('default') Style().configure("TFrame", background="white") Style().configure("TButton", font="12", padding=(5,1,5,1), background="#4285F4", foreground="white") Style().configure("TEntry", font="12", padding=(5,3,5,2)) Style().configure("TLabel", background="white") Style().map('TButton', foreground=[('pressed', 'white'), ('active', 'white')], background=[('pressed', '!disabled', '#3367d6'), ('active', '#3b78e7')], highlightcolor=[('focus','#4285F4')], relief=[('pressed', '!disabled', 'flat')]) Style().configure('Treeview', foreground='#333', background="white", highlightthickness='0') Style().map('Treeview', foreground=[('focus', '#000')], background=[('focus', '#F5F5F5')]) # ---- MENU ---- self.menubar = menubar = MenuBar(self, self.parent) # ---- TREE ---- self.filesTree = filesTree = FilesTree(self) self.filesTree.loadRecentFile() # ---- BUTTONS ---- bBrowse = Button(self, text=_("browse"), width="6", command=self.openVideo) bPlay = Button(self, text=_("play"), width="6", command=self.playVideo) # ---- GRID ---- self.grid(column=0, row=0, sticky=(N, E, W, S)) filesTree.grid(column=0, row=0, columnspan=2, rowspan=2, sticky=(N,W,E)) bBrowse.grid(column=0, row=2, sticky=(N,W)) bPlay.grid(column=0, row=2, sticky=(N,W), padx=70) self.parent.columnconfigure(0, weight=1) self.parent.rowconfigure(0, weight=1) self.columnconfigure(0, weight=1) self.columnconfigure(1, weight=1) self.rowconfigure(0, weight=1) self.rowconfigure(1, weight=1) self.centerWindow() def centerWindow(self): self.parent.update_idletasks() w = self.parent.winfo_reqwidth() + 20 h = self.parent.winfo_reqheight() + 20 sw = self.parent.winfo_screenwidth() sh = self.parent.winfo_screenheight() x = (sw - w)/4 y = (sh - h)/4 self.parent.geometry("%dx%d+%d+%d" % (w, h, x, y)) self.parent.resizable(False,False) self.parent.focus_force() self.parent.lift() def quitProgram(self): self.parent.quit() def clearRecentVideos(self): self.filesTree.clearRecentVideos() def updateRecentVideos(self, fullpath): return self.filesTree.updateRecentVideos(fullpath) def updateAndPlayVideo(self, fullpath): if self.updateRecentVideos(fullpath): self.playVideo() def openVideo(self): fullpath = fileDialog.askopenfilename( title=_('open.file') ,initialdir=self.browseInitialDir) self.updateAndPlayVideo(fullpath) def playVideo(self): lastFile = self.filesTree.getLastFile() if lastFile is not None and lastFile['fullpath'] is not '': outputAudio = '-o ' + self.menuOutputAudio.get() + ' ' adjustVideo = '-r ' if self.menuVideoRefresh.get() else '' bgBlack = '-b ' if self.menuBgBlack.get() else '' moreOptions = self.moreOptions fPath = lastFile['fullpath'].replace(' ', '\ ') cmdStr = 'omxplayer ' + outputAudio + adjustVideo + bgBlack + moreOptions + fPath self.logDebug(cmdStr) self.playProcess = Popen(['bash', '-c', cmdStr], stdin=PIPE, bufsize = 1) self.parent.focus_force() def keyEvt(self, event): self.logDebug('char: ' + event.char + ' --- key simbol: ' + event.keysym + ' --- key code: ' + str(event.keycode)) if self.playProcess is not None: # right if event.keysym == 'Right': self.playProcess.stdin.write(bytes('^[[C', 'UTF-8')) # left elif event.keysym == 'Left': self.playProcess.stdin.write(bytes('^[[D', 'UTF-8')) # up elif event.keysym == 'Up': self.playProcess.stdin.write(bytes('^[[A', 'UTF-8')) # down elif event.keysym == 'Down': self.playProcess.stdin.write(bytes('^[[B', 'UTF-8')) elif event.char == 'x': self.playProcess.kill() self.playProcess = None else: self.playProcess.stdin.write(bytes(event.char, 'UTF-8')) try: self.playProcess.stdin.flush() except IOError: try: self.playProcess.stdin.close() self.playProcess = None except IOError: self.playProcess = None self.parent.focus_force() def logDebug(self, msg): if isDebug and msg is not None: print(str(msg))
class GrepDialog(SearchDialogBase): "Dialog for searching multiple files." title = "Find in Files Dialog" icon = "Grep" needwrapbutton = 0 def __init__(self, root, engine, flist): """Create search dialog for searching for a phrase in the file system. Uses SearchDialogBase as the basis for the GUI and a searchengine instance to prepare the search. Attributes: globvar: Value of Text Entry widget for path to search. recvar: Boolean value of Checkbutton widget for traversing through subdirectories. """ SearchDialogBase.__init__(self, root, engine) self.flist = flist self.globvar = StringVar(root) self.recvar = BooleanVar(root) def open(self, text, searchphrase, io=None): "Make dialog visible on top of others and ready to use." SearchDialogBase.open(self, text, searchphrase) if io: path = io.filename or "" else: path = "" dir, base = os.path.split(path) head, tail = os.path.splitext(base) if not tail: tail = ".py" self.globvar.set(os.path.join(dir, "*" + tail)) def create_entries(self): "Create base entry widgets and add widget for search path." SearchDialogBase.create_entries(self) self.globent = self.make_entry("In files:", self.globvar)[0] def create_other_buttons(self): "Add check button to recurse down subdirectories." btn = Checkbutton( self.make_frame()[0], variable=self.recvar, text="Recurse down subdirectories") btn.pack(side="top", fill="both") def create_command_buttons(self): "Create base command buttons and add button for search." SearchDialogBase.create_command_buttons(self) self.make_button("Search Files", self.default_command, 1) def default_command(self, event=None): """Grep for search pattern in file path. The default command is bound to <Return>. If entry values are populated, set OutputWindow as stdout and perform search. The search dialog is closed automatically when the search begins. """ prog = self.engine.getprog() if not prog: return path = self.globvar.get() if not path: self.top.bell() return from idlelib.outwin import OutputWindow # leave here! save = sys.stdout try: sys.stdout = OutputWindow(self.flist) self.grep_it(prog, path) finally: sys.stdout = save def grep_it(self, prog, path): """Search for prog within the lines of the files in path. For the each file in the path directory, open the file and search each line for the matching pattern. If the pattern is found, write the file and line information to stdout (which is an OutputWindow). """ dir, base = os.path.split(path) list = self.findfiles(dir, base, self.recvar.get()) list.sort() self.close() pat = self.engine.getpat() print(f"Searching {pat!r} in {path} ...") hits = 0 try: for fn in list: try: with open(fn, errors='replace') as f: for lineno, line in enumerate(f, 1): if line[-1:] == '\n': line = line[:-1] if prog.search(line): sys.stdout.write(f"{fn}: {lineno}: {line}\n") hits += 1 except OSError as msg: print(msg) print(f"Hits found: {hits}\n(Hint: right-click to open locations.)" if hits else "No hits.") except AttributeError: # Tk window has been closed, OutputWindow.text = None, # so in OW.write, OW.text.insert fails. pass def findfiles(self, dir, base, rec): """Return list of files in the dir that match the base pattern. If rec is True, recursively iterate through subdirectories. """ try: names = os.listdir(dir or os.curdir) except OSError as msg: print(msg) return [] list = [] subdirs = [] for name in names: fn = os.path.join(dir, name) if os.path.isdir(fn): subdirs.append(fn) else: if fnmatch.fnmatch(name, base): list.append(fn) if rec: for subdir in subdirs: list.extend(self.findfiles(subdir, base, rec)) return list
class FrameFlatfileDataset(FrameCustomFileDataset): """ Holds an instance of, and visually represents, a flatfile dataset. See qal.dataset.flatfile.FlatfileDataset """ def __init__(self, _master, _dataset = None, _relief = None, _is_destination=None): super(FrameFlatfileDataset, self ).__init__(_master, _dataset, _relief, _is_destination=_is_destination) if _dataset is None: self.dataset = FlatfileDataset() def on_select(self): """Brings up a selector dialog, prompting the user to select a file, the relative path if the file is then saved to the filename property. Also, the base path is set. """ self.select_file(_default_extension = ".csv", _file_types=[('.csv files', '.csv'), ('all files', '.*')]) def init_widgets(self): # file selector self.btn_file_select=Button(self, text="Select file",command=self.on_select) self.btn_file_select.grid(column=0, row=0, columnspan=2) # filename self.filename, self.e_filename, self.l_filename = make_entry(self,"File name: ", 1) # delimiter self.delimiter, self.e_delimiter, self.l_delimiter = make_entry(self,"Delimiter: ", 2) # has_header self.l_has_header = ttk.Label(self, text="Has header: ") self.l_has_header.grid(column=0, row=3, sticky=W) self.has_header = BooleanVar() self.e_has_header = ttk.Checkbutton(self, variable=self.has_header) self.e_has_header.grid(column=1, row=3, sticky=W) # csv_dialect self.csv_dialect, self.e_csv_dialect, self.l_csv_dialect = make_entry(self,"CSV dialect: ", 4) # quoting self.quoting, self.e_quoting, self.l_quoting = make_entry(self, "Quoting: ", 5) # escapechar self.escapechar, self.e_escapechar, self.l_escapechar = make_entry(self, "Escape character: ", 6) # lineterminator self.lineterminator, self.e_lineterminator, self.l_lineterminator = make_entry(self, "Line terminator: ", 7) # quotechar self.quotechar, self.e_quotechar, self.l_quotechar = make_entry(self, "Quote character: ", 8) # skipinitialspace self.skipinitialspace, self.e_skipinitialspace, self.l_skipinitialspace = make_entry(self, "Skip initial space: ", 9) def read_from_dataset(self): super(FrameFlatfileDataset, self ).read_from_dataset() self.filename.set(empty_when_none(self.dataset.filename)) self.delimiter.set(empty_when_none(self.dataset.delimiter)) self.has_header.set(bool_to_binary_int(self.dataset.has_header)) self.csv_dialect.set(empty_when_none(self.dataset.csv_dialect)) self.quoting.set(empty_when_none(self.dataset.quoting)) self.escapechar.set(empty_when_none(self.dataset.escapechar)) self.lineterminator.set(empty_when_none(self.dataset.lineterminator)) self.quotechar.set(empty_when_none(self.dataset.quotechar)) self.skipinitialspace.set(empty_when_none(self.dataset.skipinitialspace)) def write_to_dataset(self): super(FrameFlatfileDataset, self ).write_to_dataset() if self.dataset is None: self.dataset = FlatfileDataset() self.dataset.filename = self.filename.get() self.dataset.delimiter = self.delimiter.get() self.dataset.has_header = self.has_header.get() self.dataset.csv_dialect = self.csv_dialect.get() self.dataset.quoting = self.quoting.get() self.dataset.escapechar = self.escapechar.get() self.dataset.lineterminator = self.lineterminator.get() self.dataset.quotechar = self.quotechar.get() self.dataset.skipinitialspace = self.skipinitialspace.get() def reload(self): self.notify_task("Load file "+ self.dataset.filename, 10) self.dataset.load() self.notify_task("Loaded filed "+ self.dataset.filename + ".", 100) def get_possible_references(self, _force = None): if not self.dataset.field_names or _force == True: self.reload() self.references = self.dataset.field_names return self.dataset.field_names def check_reload(self): _filename = self.filename.get() if not os.path.isabs(_filename) and self.base_path is None: return "First save the merge. You use a relative path to the flatfile dataset." else: return False
class YdlGUI(Frame): def __init__(self, parent): Frame.__init__(self, parent) self.parent = parent self.pack(fill=BOTH, expand=True) self.parent.title("youtube-dl GUI") # Initialise variables self._extract_audio = BooleanVar() self._video_url = StringVar() self._output_path = StringVar() # Initialise self._logger = LogWindow(self) self._init_ui() def _init_ui(self): # Label to specify video link lbl_video_url = Label(self, text="Video URL:") lbl_video_url.place(x=20, y=20) # Entry to enter video url entr_video_url = Entry(self, width=50, textvariable=self._video_url) entr_video_url.place(x=100, y=20) # Checkbutton to extract audio cb_extract_audio = Checkbutton(self, var=self._extract_audio, text="Only keep audio") cb_extract_audio.pack() cb_extract_audio.place(x=20, y=60) # Button to browse for location b_folder_choose = Button(self, text="Choose output directory", command=self.ask_directory) b_folder_choose.place(x=150, y=90) # Button to start downloading b_start_download = Button(self, text="Start download", command=self.download) b_start_download.place(x=20, y=90) # Log window to log progress self._logger.place(x=20, y=130) def ask_directory(self): self._output_path.set(file_dialog.askdirectory()) def start_youtube_dl(self): # Start downloading the specified url if self._output_path.get(): output_path = self._output_path.get() else: try: output_path = os.path.dirname(os.path.abspath(__file__)) except NameError: import sys output_path = os.path.dirname(os.path.abspath(sys.argv[0])) output_tmpl = output_path + '/%(title)s-%(id)s.%(ext)s' options = { 'format': 'bestvideo[ext=mp4]+bestaudio[ext=m4a]/bestvideo+bestaudio/best', 'merge_output_format': 'mp4', 'socket_timeout': '15', 'progress_hooks': [self._logger.log], 'ignoreerrors': True, 'outtmpl': output_tmpl, } if self._extract_audio.get(): options['format'] = 'bestaudio/best', options['postprocessors'] = [{ 'key': 'FFmpegExtractAudio', 'preferredcodec': 'mp3', 'preferredquality': '3', }] dl = YoutubeDL(options) status = dl.download([self._video_url.get()]) if status != 0: mbox.showerror("youtube-dl error", "An error happened whilst processing your video(s)") else: mbox.showinfo("youtube-dl finished", "Your video(s) have been successfully processed") def download(self): thr = Thread(target=self.start_youtube_dl) thr.start()
def test_get(self): v = BooleanVar(self.root, True, "name") self.assertAlmostEqual(True, v.get()) self.root.globalsetvar("name", "0") self.assertAlmostEqual(False, v.get())
class MarkovDemo(Frame): "MarkovDemo(master=None, **kw) -> MarkovDemo instance" TEXT = dict(height=2, width=46, wrap=WORD) # Text Options GRID = dict(padx=5, pady=5) # Grid Options # Initialize a MarkovDemo instance with a GUI for interaction. def __init__(self, master=None, **kw): "Initialize the MarkovDemo instance's widgets and settings." super().__init__(master, **kw) self.build_widgets() self.place_widgets() self.setup_widgets() self.grid_rowconfigure(2, weight=1) self.grid_rowconfigure(3, weight=1) self.grid_columnconfigure(0, weight=1) self.key = self.primer = None def build_widgets(self): "Build the various widgets that will be used in the program." # Create processing frame widgets. self.processing_frame = LabelFrame(self, text='Processing Mode:') self.mode_var = StringVar(self, 'encode') self.decode_button = Radiobutton(self.processing_frame, text='Decode Cipher-Text', command=self.handle_radiobuttons, value='decode', variable=self.mode_var) self.encode_button = Radiobutton(self.processing_frame, text='Encode Plain-Text', command=self.handle_radiobuttons, value='encode', variable=self.mode_var) self.freeze_var = BooleanVar(self, False) self.freeze_button = Checkbutton(self.processing_frame, text='Freeze Key & Primer', command=self.handle_checkbutton, offvalue=False, onvalue=True, variable=self.freeze_var) # Create encoding frame widgets. self.encoding_frame = LabelFrame(self, text='Encoding Options:') self.chain_size_label = Label(self.encoding_frame, text='Chain Size:') self.chain_size_entry = Entry(self.encoding_frame) self.plain_text_label = Label(self.encoding_frame, text='Plain-Text:') self.plain_text_entry = Entry(self.encoding_frame) # Create input frame widgets. self.input_frame = LabelFrame(self, text='Input Area:') self.input_text = ScrolledText(self.input_frame, **self.TEXT) # Create output frame widgets. self.output_frame = LabelFrame(self, text='Output Area:') self.output_text = ScrolledText(self.output_frame, **self.TEXT) def place_widgets(self): "Place the widgets where they belong in the MarkovDemo frame." # Locate processing frame widgets. self.processing_frame.grid(sticky=EW, **self.GRID) self.decode_button.grid(row=0, column=0, **self.GRID) self.encode_button.grid(row=0, column=1, **self.GRID) self.freeze_button.grid(row=0, column=2, **self.GRID) # Locate encoding frame widgets. self.encoding_frame.grid(sticky=EW, **self.GRID) self.chain_size_label.grid(row=0, column=0, sticky=W, **self.GRID) self.chain_size_entry.grid(row=0, column=1, sticky=EW, **self.GRID) self.plain_text_label.grid(row=1, column=0, sticky=W, **self.GRID) self.plain_text_entry.grid(row=1, column=1, sticky=EW, **self.GRID) self.encoding_frame.grid_columnconfigure(1, weight=1) # Locate input frame widgets. self.input_frame.grid(sticky=NSEW, **self.GRID) self.input_text.grid(sticky=NSEW, **self.GRID) self.input_frame.grid_rowconfigure(0, weight=1) self.input_frame.grid_columnconfigure(0, weight=1) # Locate output frame widgets. self.output_frame.grid(sticky=NSEW, **self.GRID) self.output_text.grid(sticky=NSEW, **self.GRID) self.output_frame.grid_rowconfigure(0, weight=1) self.output_frame.grid_columnconfigure(0, weight=1) def setup_widgets(self): "Setup each widget's configuration for the events they handle." self.input_text.bind('<Key>', self.handle_key_events) self.input_text.bind('<Control-Key-a>', self.handle_control_a) self.input_text.bind('<Control-Key-/>', lambda event: 'break') self.output_text['state'] = DISABLED self.output_text.bind('<Control-Key-a>', self.handle_control_a) self.output_text.bind('<Control-Key-/>', lambda event: 'break') ######################################################################## # Take care of any special event needing dedicated processing. def handle_radiobuttons(self): "Change the interface based on the encoding / decoding setting." if self.encrypting: self.freeze_button.grid() if not self.freeze_var.get(): self.encoding_frame.grid() else: self.freeze_button.grid_remove() if not self.freeze_var.get(): self.encoding_frame.grid_remove() self.handle_key_events(None) def handle_checkbutton(self): "Change the interface based on the key / primer freeze setting." if self.freeze_var.get(): self.encoding_frame.grid_remove() else: self.encoding_frame.grid() def handle_key_events(self, event): "Schedule refreshing the output area after an input area event." if event is None or event.char and event.state | 0o11 == 0o11: self.after_idle(self.refresh) @staticmethod def handle_control_a(event): "Select all text in the widget associated with the given event." event.widget.tag_add(SEL, 1.0, END + '-1c') return 'break' ######################################################################## # Handle interface's updates when either encoding or decoding. def refresh(self): "Refresh the output based on the value of the input." text = self.input_text.get(1.0, END + '-1c') if not text: self.output = text elif self.encrypting: self.encode(text) else: self.decode(text) def output(self, value): "Set the text in the output area to the string value." self.output_text['state'] = NORMAL self.output_text.delete(1.0, END) self.output_text.insert(END, value) if self.encrypting and self.freeze_var.get(): self.output_text.see(END) self.output_text['state'] = DISABLED output = property(fset=output, doc='Output area property.') @property def chain_size(self): "Chain size for the Markov chains used when encrypting." try: value = ast.literal_eval(self.chain_size_entry.get()) assert isinstance(value, int) and 2 <= value <= 256 return value except: self.chain_size_entry.delete(0, END) self.chain_size_entry.insert(0, '2') return 2 @property def plain_text(self): "Plain text or ignored characters in encryption process." try: value = self.repr_to_obj(self.plain_text_entry.get(), '') assert isinstance(value, str) return value except: self.plain_text_entry.delete(0, END) return '' ######################################################################## # Encrypt a string for display in the interface's output area. def encode(self, string): "Encode the string and show the cipher-text in the output." try: cipher = self.build_cipher(string) except ValueError: self.output = '' except: self.output = traceback.format_exc() else: self.output = self.build_header() + '\n\n' + cipher def build_cipher(self, string): "Build cipher-text based on plain-text and return answer." if self.key and self.freeze_var.get(): cipher, primer = me.encrypt_str(string, self.key, self.primer) else: args = string, self.chain_size, self.plain_text cipher, self.key, self.primer = me.auto_encrypt_str(*args) return cipher def build_header(self): "Build header from key and primer values in current use." header = '\n'.join(map(self.bytes_to_repr, self.key.data)) header += '\n' + self.bytes_to_repr(self.primer.data) return header ######################################################################## # Decrypt a string for display in the interface's output area. def decode(self, string): "Decode encrypted message and display plain-text in output." try: cipher = self.extract_keys(string) text = self.extract_text(cipher) except ValueError: self.output = '' except: self.output = traceback.format_exc() else: self.output = text def extract_keys(self, string): "Extract keys to decryption and return the cipher-text area." header, cipher = string.split('\n\n', 1) *key, primer = map(self.repr_to_obj, header.split('\n')) self.key, self.primer = me.Key(tuple(key)), me.Primer(primer) return cipher def extract_text(self, string): "Extract text message from string using built key and primer." text, primer = me.decrypt_str(string, self.key, self.primer) return text ######################################################################## # Provide some special methods to simplify the program's code. @property def encrypting(self): "Encrypting boolean stating current operations mode." return {'encode': True, 'decode': False}[self.mode_var.get()] @staticmethod def bytes_to_repr(obj): "Convert bytes object into suitable representation." if not isinstance(obj, bytes): raise TypeError('Object must be a bytes instance!') return repr(obj)[2:-1] @staticmethod def repr_to_obj(string, prefix='b'): "Convert representation into an equivalent object." for template in '{}"{}"', "{}'{}'": try: return ast.literal_eval(template.format(prefix, string)) except: pass raise ValueError('Cannot convert {!r} to object!'.format(string)) @classmethod def main(cls): "Create context for demo and run a test instance." NoDefaultRoot() root = Tk() root.minsize(420, 330) root.title('Markov Demo 2') test = cls(root) test.grid(sticky=NSEW) root.grid_rowconfigure(0, weight=1) root.grid_columnconfigure(0, weight=1) root.mainloop()
class Xls2kml(object): ''' Interface builted in Tkinter() ''' def __init__(self): ''' None -> None Builds the Tkinter window and all his elements. ''' # variables ---------------------------------------------------- # log file open("erros.log", "w").close() # to open and clean the logfile logging.basicConfig(level=logging.DEBUG, filename='erros.log') sys.stderr = LogFile('stderr') # Redirect stderr self.original_working_dir = os.getcwd() # original working dir self.master = Tk() # Tk() object self.master.title('EXCEL to KMZ Transformer - ver. 1.6') # window name icons = os.getcwd() + os.sep + "icons" + os.sep # path to icons foto_folder = os.getcwd() + os.sep + "fotos" # path to fotos icon = icons + "compass.ico" self.master.iconbitmap(icon) # window icon self.master.resizable(width=FALSE, height=FALSE) self.master.geometry("548x314") self.file_name = "" # the name of the EXEL file self.last_dir = "C:/" # image to decorate the window self.img = ImageTk.PhotoImage(Image.open(icons + "excel-kmz.jpg")) # to use in frame, message, labels and buttons ----------------- self.message = StringVar() self.message.set("\nSelecciona um ficheiro EXCEL") bg = "gray25" bg1 = "dark orange" fc = "white smoke" font = ("Helvetica", "8", "bold") text0 = " ----- " # " ------------------------------------------ " text1 = " Boris & Vladimir Software " text = text0 + text1 + text0 # Menu --------------------------------------------------------- self.menu = Menu(self.master) self.master.config(menu=self.menu) filemenu = Menu(self.menu) self.menu.add_cascade(label="Ficheiro", menu=filemenu) filemenu.add_command(label="Sair", command=self.__callback_3) filemenu.add_command(label='Pasta Fotos', command=lambda: (self.__open_folder(foto_folder))) # --------------------- NOVO ----------------------------------- self.openGE = BooleanVar() # não esquecer de importar BooleanVar self.openGE.set(False) optionsmenu = Menu(self.menu) self.menu.add_cascade(label="Opções", menu=optionsmenu) optionsmenu.add_checkbutton(label="Não abrir o Google Earth", onvalue=True, offvalue=False, variable=self.openGE) docsmenu = Menu(self.menu) docs = ["docs\manual.pdf", "docs\icons.pdf", "docs\colors.pdf", "docs\GPS.xlsx", "docs\GPS.kmz", "docs\Celulas.xlsx", "docs\Celulas.kmz", "docs\Foto.xlsx", "docs\Foto.kmz", "docs\Quadrado.xls", "docs\Quadrado.kmz"] self.menu.add_cascade(label="Documentação", menu=docsmenu) docsmenu.add_command(label="Manual", command=lambda: (self.__open_file(docs[0]))) docsmenu.add_command(label="Ícones", command=lambda: (self.__open_file(docs[1]))) docsmenu.add_command(label="Cores", command=lambda: (self.__open_file(docs[2]))) exemplemenu = Menu(docsmenu) docsmenu.add_cascade(label="Exemplos", menu=exemplemenu) gpsmenu = Menu(exemplemenu) exemplemenu.add_cascade(label="Trajetos", menu=gpsmenu) gpsmenu.add_command(label="Excel", command=lambda: (self.__open_file(docs[3]))) gpsmenu.add_command(label="Google Earth", command=lambda: (self.__open_file(docs[4]))) cellmenu = Menu(exemplemenu) exemplemenu.add_cascade(label="Células Telefónicas", menu=cellmenu) cellmenu.add_command(label="Excel", command=lambda: (self.__open_file(docs[5]))) cellmenu.add_command(label="Google Earth", command=lambda: (self.__open_file(docs[6]))) fotomenu = Menu(exemplemenu) exemplemenu.add_cascade(label="Fotos", menu=fotomenu) fotomenu.add_command(label="Excel", command=lambda: (self.__open_file(docs[7]))) fotomenu.add_command(label="Google Earth", command=lambda: (self.__open_file(docs[8]))) squaremenu = Menu(exemplemenu) exemplemenu.add_cascade(label="Quadrado", menu=squaremenu) squaremenu.add_command(label="Excel", command=lambda: (self.__open_file(docs[9]))) squaremenu.add_command(label="Google Earth", command=lambda: (self.__open_file(docs[10]))) helpmenu = Menu(self.menu) self.menu.add_cascade(label='Ajuda', menu=helpmenu) helpmenu.add_command(label="Sobre", command=self.__about) helpmenu.add_command(label="Ver erros", command=lambda: (self.__open_file("erros.log"))) # Frame to suport butons, labels and separators ---------------- self.f = Frame(self.master, bg=bg) self.f.pack_propagate(0) # don't shrink self.f.pack(side=BOTTOM, padx=0, pady=0) # Message and Labels ------------------------------------------- self.l1 = Message( self.f, bg=bg1, bd=5, fg=bg, textvariable=self.message, font=("Helvetica", "13", "bold italic"), width=500).grid( row=0, columnspan=6, sticky=EW, padx=5, pady=5) self.l2 = Label( self.f, image=self.img, fg=bg ).grid(row=1, columnspan=6, padx=5, pady=2) self.l6 = Label( self.f, text=text, font=("Helvetica", "11", "bold"), bg=bg, fg=bg1 ).grid(row=3, column=2, columnspan=3, sticky=EW, pady=5) # Buttons ------------------------------------------------------ self.b0 = Button( self.f, text="Abrir EXCEL...", command=self.__callback, width=10, bg="forest green", fg=fc, font=font ).grid(row=3, column=0, padx=5, sticky=W) self.b1 = Button( self.f, text="Gravar KMZ", command=self.__callback_2, width=10, bg="DodgerBlue4", fg=fc, font=font ).grid(row=3, column=1, sticky=W) self.b2 = Button( self.f, text="Sair", command=self.__callback_3, width=10, bg="orange red", fg=fc, font=font ).grid(row=3, column=5, sticky=E, padx=5) # Separator ---------------------------------------------------- # self.s = ttk.Separator(self.f, orient=HORIZONTAL).grid( # row=4, columnspan=5, sticky=EW, padx=5, pady=5) # Progressbar -------------------------------------------------- # self.pb = Canvas(self.f, width=260, height=10) self.s = ttk.Style() # themes: winnative, clam, alt, default, classic, vista, xpnative self.s.theme_use('winnative') self.s.configure("red.Horizontal.TProgressbar", foreground='green', background='forest green') self.pb = ttk.Progressbar(self.f, orient='horizontal', mode='determinate', style="red.Horizontal.TProgressbar") self.pb.grid(row=2, column=0, columnspan=6, padx=5, pady=5, sticky=EW) # Mainloop ----------------------------------------------------- self.master.mainloop() def __callback(self): # "Abrir EXEL..." button handler ------------ ''' None -> None Opens a new window (filedialog.askopenfilename) to choose the EXCEL file that is necessary to make the KMZ file. ''' title = 'Selecciona um ficheiro Excel' message = 'Ficheiro EXCEL carregado em memória.\nTransforma-o em KMZ!' self.file_name = filedialog.askopenfilename(title=title, initialdir=self.last_dir) self.last_dir = self.file_name[:self.file_name.rfind('/')] if self.file_name[self.file_name.rfind('.')+1:] != 'xls' and \ self.file_name[self.file_name.rfind('.')+1:] != 'xlsx': message = self.file_name + ' não é um ficheiro Excel válido!' self.message.set(message) def __callback_2(self): # "Gravar KMZ" button handler --------------- ''' None -> None Calls the function self.__threat() ''' sleep(1) message = 'Ficheiro EXCEL carregado em memória.\nTransforma-o em KMZ!' if self.message.get() != message: self.message.set("\nEscolhe um ficheiro EXCEL primeiro") self.master.update_idletasks() else: self.message.set("\nA processar...") self.master.update_idletasks() sleep(1) self.__threads() def __callback_3(self): # "Sair" button handler --------------------- ''' None -> None Kills the window ''' self.master.destroy() def __threads(self): ''' None -> MyTread() objects Creates two threads to run at the same time the functions: self.__create_kmz() self.__progressbar() ''' funcs = [self.__create_kmz, self.__progressbar] threads = [] nthreads = list(range(len(funcs))) for i in nthreads: t = MyThread(funcs[i], (), funcs[i].__name__) threads.append(t) for i in nthreads: threads[i].start() def __create_kmz(self): ''' None -> None Calls the exel_to_kml() atribute of the MotherControl() class And when it returns, calls self.__open_Google_Earth() ''' kmz = MotherControl(self.file_name, self.original_working_dir).exel_to_kml() if type(kmz) == str: self.message.set(kmz) self.pb.stop() self.master.update_idletasks else: sleep(2) self.pb.stop() self.master.update_idletasks() self.__open_Google_Earth() def __open_Google_Earth(self): ''' None -> None Opens the maded KMZ file in Google Earth ''' sleep(1) self.master.update_idletasks() if not self.openGE.get(): self.message.set("KMZ gravado com sucesso.\nA abrir o Google Earth...") else: self.message.set("\nKMZ gravado com sucesso.\n") sleep(2) self.master.update_idletasks() path = self.file_name[:self.file_name.rindex('/')] path_1 = self.file_name[self.file_name.rindex('/')+1:self.file_name.rfind('.')] kmzs = [x for x in os.listdir(path) if x[-4:] == '.kmz' and x[:-12] == path_1] kmzs.sort() try: if not self.openGE.get(): os.startfile(path + os.sep + kmzs[-1]) sleep(2) self.message.set("\nSelecciona um ficheiro EXCEL") except: self.message.set("Instale o Google Earth\nhttp://www.google.com/earth/") self.master.update_idletasks() def __progressbar(self, ratio=0): ''' None -> None Starts the progressbar in the window ''' self.pb.start(50) def __about(self): ''' None -> None Associated with the Help Menu. Creates a new window with the "About" information ''' appversion = "1.6" appname = "EXCEL to KML Transformer" copyright = 14 * ' ' + '(c) 2013' + 12 * ' ' + \ 'SDATO - DP - UAF - GNR\n' + 34 * ' '\ + "All Rights Reserved" licence = 18 * ' ' + 'http://opensource.org/licenses/GPL-3.0\n' contactname = "Nuno Venâncio" contactphone = "(00351) 969 564 906" contactemail = "*****@*****.**" message = "Version: " + appversion + 5 * "\n" message0 = "Copyright: " + copyright + "\n" + "Licença: " + licence message1 = contactname + '\n' + contactphone + '\n' + contactemail icons = os.getcwd() + os.sep + "icons" + os.sep # path to icons icon = icons + "compass.ico" tl = Toplevel(self.master) tl.configure(borderwidth=5) tl.title("Sobre...") tl.iconbitmap(icon) tl.resizable(width=FALSE, height=FALSE) f1 = Frame(tl, borderwidth=2, relief=SUNKEN, bg="gray25") f1.pack(side=TOP, expand=TRUE, fill=BOTH) l0 = Label(f1, text=appname, fg="white", bg="gray25", font=('courier', 16, 'bold')) l0.grid(row=0, column=0, sticky=W, padx=10, pady=5) l1 = Label(f1, text=message, justify=CENTER, fg="white", bg="gray25") l1.grid(row=2, column=0, sticky=E, columnspan=3, padx=10, pady=0) l2 = Label(f1, text=message0, justify=LEFT, fg="white", bg="gray25") l2.grid(row=6, column=0, columnspan=2, sticky=W, padx=10, pady=0) l3 = Label(f1, text=message1, justify=CENTER, fg="white", bg="gray25") l3.grid(row=7, column=0, columnspan=2, padx=10, pady=0) button = Button(tl, text="Ok", command=tl.destroy, width=10) button.pack(pady=5) def __open_file(self, doc): try: os.startfile(doc) except: pass # os.system(doc) # não gosto disto mas os.startfile(doc) # faz com que a janela não se desenhe bem def __open_folder(self, folder): os.system('start explorer "' + folder + '"')
class GraphicalUserInterface(Frame): def __init__(self, parent): Frame.__init__(self, parent) self.parent = parent self.__initUI() def __initUI(self): self.parent.title("Fuel Manager") # parameters that the user can modify self.__exchvar = BooleanVar() self.__exchrate = True self.__datevar = BooleanVar() self.__datetime = True self.__empty_tank_var = BooleanVar() self.__empty_tank = False self.__airport_file = "input files/airport.csv" self.__aircraft_file = "input files/aircraft.csv" self.__currency_file = "input files/countrycurrency.csv" self.__exchange_rate_file = "input files/currencyrates.csv" self.__itinerary_file = "input files/testroutes.csv" self.__output_file = "bestroutes/bestroutes.csv" self.__home_airport = ["DUB"] self.__other_airports = ["LHR", "CDG", "JFK", "AAL", "AMS", "ORK"] self.__hubs = ["MHP"] self.__stopover_cost = 0 self.__constraints = "JFK AAL / JFK CDG" self.__aircraft_code = "747" # main frame frame = Frame(self, relief=RAISED, borderwidth=1) frame.pack(fill=BOTH, expand=True) self.pack(fill=BOTH, expand=True) # manage single itinerary frame self.manual_frame = LabelFrame(self, text="Manage a single itinerary", font=("Helvetica", 14), width=300) self.manual_frame.place(x=50, y=50) # Empty row to put some space between the other rows and to control the width of this frame because # I don't know what I'm doing self.empty_label = Label(self.manual_frame, text=" ", width=60, height=1, font=("Helvetica", 1)) self.empty_label.grid(row=0, sticky="W") # Text field where user can enter home airport self.home_airport_label = Label(self.manual_frame, width=22, text="Home airport:", anchor='w') self.home_airport_label.grid(row=1, sticky="W") self.home_airport_entry = Entry(self.manual_frame, width=50) self.home_airport_entry.grid(row=2, sticky="E") self.home_airport_entry.insert(0, self.__home_airport) self.empty_label = Label(self.manual_frame, text=" ", width=60, height=1, font=("Helvetica", 1)) self.empty_label.grid(row=3, sticky="W") # Text field where user can enter other airports self.other_airports_label = Label(self.manual_frame, width=22, text="Other airports:", anchor='w') self.other_airports_label.grid(row=4, sticky="W") self.other_airports_entry = Entry(self.manual_frame, width=50) self.other_airports_entry.grid(row=5, sticky="E") self.other_airports_entry.insert(0, self.__other_airports) self.empty_label = Label(self.manual_frame, text=" ", width=60, height=1, font=("Helvetica", 1)) self.empty_label.grid(row=6, sticky="W") # Text field where user can enter aircraft code self.aircraft_label = Label(self.manual_frame, width=22, text="Aircraft code:", anchor='w') self.aircraft_label.grid(row=7, sticky="W") self.aircraft_entry = Entry(self.manual_frame, width=50) self.aircraft_entry.grid(row=8, sticky="E") self.aircraft_entry.insert(0, self.__aircraft_code) self.empty_label = Label(self.manual_frame, text=" ", width=60, height=1, font=("Helvetica", 1)) self.empty_label.grid(row=9, sticky="W") # Text field where user can enter constraints self.constraints_label = Label(self.manual_frame, width=22, text="Constraints:", anchor='w') self.constraints_label.grid(row=13, sticky="W") self.constraints_entry = Entry(self.manual_frame, width=50) self.constraints_entry.grid(row=14, sticky="E") self.constraints_entry.insert(0, self.__constraints) self.constraints_explanation_label = \ Label(self.manual_frame, width=50, text="Each constraint should consist of three-letter airport codes" "\nseparated by spaces. To enter more than one constraint," "\nuse ' / ' to separate them", anchor='w', justify='left') self.constraints_explanation_label.grid(row=15, sticky="W") self.empty_label = Label(self.manual_frame, text=" ", width=60, height=1, font=("Helvetica", 1)) self.empty_label.grid(row=16, sticky="W") # run button self.run_button = Button(self.manual_frame, text='Manage itinerary', command=self.__manage_single_itinerary, bg="#CCE1E8") self.run_button.grid(row=16, sticky="E") # manage list of itineraries frame self.itinerary_list_frame = LabelFrame(self, text="Manage a list of itineraries", font=("Helvetica", 14), width=300) self.itinerary_list_frame.place(x=50, y=375) # Empty row to put some space between the other rows and to control the width of this frame self.empty_label = Label(self.itinerary_list_frame, text=" ", width=60, height=1, font=("Helvetica", 1)) self.empty_label.grid(row=12, sticky="W") # Text field where user can enter itinerary filepath self.itinerary_label = Label(self.itinerary_list_frame, width=22, text="Itinerary list: ", anchor='w') self.itinerary_label.grid(row=13, sticky="W") self.itinerary_entry = Entry(self.itinerary_list_frame, width=50) self.itinerary_entry.grid(row=13, sticky="E") self.itinerary_entry.insert(0, self.__itinerary_file) self.itinerary_button = Button(self.itinerary_list_frame, text='Browse...', command=self.__get_itinerary_filename) self.itinerary_button.grid(row=14, sticky="E") self.empty_label = Label(self.itinerary_list_frame, text=" ", width=60, height=2, font=("Helvetica", 1)) self.empty_label.grid(row=15, sticky="W") # run button self.run_button = Button(self.itinerary_list_frame, text='Manage list of itineraries', command=self.__manage_list, bg="#CCE1E8") self.run_button.grid(row=16, sticky="E") # Fuel management settings frame self.general_frame = LabelFrame(self, text="Fuel management settings", font=("Helvetica", 14), width=300) self.general_frame.place(x=500, y=50) # Empty row to put some space between the other rows and to control the width of this frame self.empty_label = Label(self.general_frame, text=" ", width=60, height=1, font=("Helvetica", 1)) self.empty_label.grid(row=0, sticky="W") # Text field where user can enter hubs self.hubs_label = Label(self.general_frame, width=22, text="Hubs:", anchor='w') self.hubs_label.grid(row=1, sticky="W") self.hubs_entry = Entry(self.general_frame, width=50) self.hubs_entry.grid(row=2, sticky="E") self.hubs_entry.insert(0, self.__hubs) self.empty_label = Label(self.general_frame, text=" ", width=60, height=1, font=("Helvetica", 1)) self.empty_label.grid(row=3, sticky="W") # Text field where user can enter cost of extra stopovers self.stopover_cost_label = Label(self.general_frame, width=40, text="Cost of each extra stopover (euros):", anchor='w') self.stopover_cost_label.grid(row=4, sticky="W") self.stopover_cost_entry = Entry(self.general_frame, width=50) self.stopover_cost_entry.grid(row=5, sticky="E") self.stopover_cost_entry.insert(0, self.__stopover_cost) self.empty_label = Label(self.general_frame, text=" ", width=60, height=1, font=("Helvetica", 1)) self.empty_label.grid(row=6, sticky="W") # bring home extra fuel checkbox self.empty_tank_cb = Checkbutton(self.general_frame, text="Always return to home airport with an empty tank", variable=self.__empty_tank_var, command=self.__empty_tank_toggle) self.empty_tank_cb.grid(row=7, sticky="W") self.empty_label = Label(self.general_frame, text=" ", width=60, height=1, font=("Helvetica", 1)) self.empty_label.grid(row=8, sticky="W") # manage inputs frame self.input_frame = LabelFrame(self, text="Inputs", font=("Helvetica", 14), width=300) self.input_frame.place(x=500, y=250) self.empty_label = Label(self.input_frame, text=" ", width=60, height=1, font=("Helvetica", 1)) self.empty_label.grid(row=0, sticky="W") # Text field where user can enter airport filepath self.airport_label = Label(self.input_frame, width=22, text="Airport list: ", anchor='w') self.airport_label.grid(row=1, sticky="W") self.airport_entry = Entry(self.input_frame, width=50) self.airport_entry.grid(row=1, sticky="E") self.airport_entry.insert(0, self.__airport_file) self.airport_button = Button(self.input_frame, text='Browse...', command=self.__get_airport_filename) self.airport_button.grid(row=2, sticky="E") self.empty_label = Label(self.input_frame, text=" ", width=60, height=1, font=("Helvetica", 1)) self.empty_label.grid(row=3, sticky="W") # Text field where user can enter aircraft filepath self.aircraft_file_label = Label(self.input_frame, width=22, text="Aircraft list: ", anchor='w') self.aircraft_file_label.grid(row=4, sticky="W") self.aircraft_file_entry = Entry(self.input_frame, width=50) self.aircraft_file_entry.grid(row=4, sticky="E") self.aircraft_file_entry.insert(0, self.__aircraft_file) self.aircraft_file_button = Button(self.input_frame, text='Browse...', command=self.__get_aircraft_filename) self.aircraft_file_button.grid(row=5, sticky="E") self.empty_label = Label(self.input_frame, text=" ", width=425, height=1, font=("Helvetica", 1)) self.empty_label.grid(row=6, sticky="W") # Text field where user can enter country-currency filepath self.currency_label = Label(self.input_frame, width=22, text="Currency list: ", anchor='w') self.currency_label.grid(row=7, sticky="W") self.currency_entry = Entry(self.input_frame, width=50) self.currency_entry.grid(row=7, sticky="E") self.currency_entry.insert(0, self.__currency_file) self.currency_button = Button(self.input_frame, text='Browse...', command=self.__get_currency_filename) self.currency_button.grid(row=8, sticky="E") self.empty_label = Label(self.input_frame, text=" ", width=60, height=1, font=("Helvetica", 1)) self.empty_label.grid(row=9, sticky="W") # Text field where user can enter exchange rate filepath self.exchange_rate_label = Label(self.input_frame, width=22, text="Exchange rate list: ", anchor='w') self.exchange_rate_label.grid(row=10, sticky="W") self.exchange_rate_entry = Entry(self.input_frame, width=50) self.exchange_rate_entry.grid(row=10, sticky="E") self.exchange_rate_entry.insert(0, self.__exchange_rate_file) self.exchange_rate_button = Button(self.input_frame, text='Browse...', command=self.__get_exchange_rate_filename) self.exchange_rate_button.grid(row=11, sticky="E") # real-time exchange rates checkbox self.forex = Checkbutton(self.input_frame, text="Use real-time exchange rates", variable=self.__exchvar, command=self.__forex_toggle) self.forex.select() self.forex.grid(row=12, sticky="W") # manage output frame self.output_frame = LabelFrame(self, text="Output", font=("Helvetica", 14), width=300) self.output_frame.place(x=500, y=550) self.empty_label = Label(self.output_frame, text=" ", width=60, height=1, font=("Helvetica", 1)) self.empty_label.grid(row=0, sticky="W") # Text field where user can enter output filepath self.output_label = Label(self.output_frame, width=22, text="Output file: ", anchor='w') self.output_label.grid(row=1, sticky="W") self.output_entry = Entry(self.output_frame, width=50) self.output_entry.grid(row=1, sticky="E") self.output_entry.insert(0, self.__output_file) self.output_button = Button(self.output_frame, text='Browse...', command=self.__get_output_filename) self.output_button.grid(row=2, sticky="E") # append date to output filename checkbox self.datetime_cb = Checkbutton(self.output_frame, text="Append date and time to filename (e.g., bestroutes 20151218 160000.csv)", variable=self.__datevar, command=self.__datetime_toggle) self.datetime_cb.grid(row=3, sticky="W") self.datetime_cb.select() # GUI methods def __forex_toggle(self): if self.__exchvar.get() == True: self.__exchrate = True else: self.__exchrate = False def __datetime_toggle(self): if self.__datevar.get() == True: self.__datetime = True else: self.__datetime = False def __empty_tank_toggle(self): if self.__empty_tank_var.get() == True: self.__empty_tank = True else: self.__empty_tank = False def __get_airport_filename(self): self.__airport_file = filedialog.askopenfilename( filetypes=(("Comma-separated values files", "*.csv"), ("All files", "*.*"))) self.airport_entry.delete(0, END) self.airport_entry.insert(0, self.__airport_file) def __get_aircraft_filename(self): self.__aircraft_file = filedialog.askopenfilename( filetypes=(("Comma-separated values files", "*.csv"), ("All files", "*.*"))) self.aircraft_file_entry.delete(0, END) self.aircraft_file_entry.insert(0, self.__aircraft_file) def __get_currency_filename(self): self.__currency_file = filedialog.askopenfilename( filetypes=(("Comma-separated values files", "*.csv"), ("All files", "*.*"))) self.currency_entry.delete(0, END) self.currency_entry.insert(0, self.__currency_file) def __get_exchange_rate_filename(self): self.__exchange_rate_file = filedialog.askopenfilename( filetypes=(("Comma-separated values files", "*.csv"), ("All files", "*.*"))) self.exchange_rate_entry.delete(0, END) self.exchange_rate_entry.insert(0, self.__exchange_rate_file) def __get_itinerary_filename(self): self.__itinerary_file = filedialog.askopenfilename( filetypes=(("Comma-separated values files", "*.csv"), ("All files", "*.*"))) self.itinerary_entry.delete(0, END) self.itinerary_entry.insert(0, self.__itinerary_file) def __get_output_filename(self): self.__output_file = filedialog.asksaveasfilename(defaultextension=".csv", filetypes=( ("Comma-separated values file", "*.csv"), ("All Files", "*.*"))) self.output_entry.delete(0, END) self.output_entry.insert(0, self.__output_file) def __manage_list(self): # validate user inputs hubs, stopover_cost = validate_inputs_for_list_of_itineraries(self.hubs_entry.get().upper().split(), self.stopover_cost_entry.get()) print("Managing list of itineraries...") manage_list_of_routes(self.__exchrate, self.__datetime, self.__empty_tank, hubs, stopover_cost, self.itinerary_entry.get(), self.airport_entry.get(), self.aircraft_file_entry.get(), self.currency_entry.get(), self.exchange_rate_entry.get(), self.output_entry.get()) def __manage_single_itinerary(self): # validate user inputs try: hubs, stopover_cost, constraints_list, home_airport, other_airports, aircraft_code = \ validate_inputs_for_single_itinerary(self.hubs_entry.get().upper().split(), self.stopover_cost_entry.get(), self.constraints_entry.get().upper().split(), self.home_airport_entry.get().upper(), self.other_airports_entry.get().upper().split(), self.aircraft_entry.get().upper()) except TypeError: return print("Managing single itinerary...") manage_single_route(home_airport, other_airports, aircraft_code, self.__exchrate, self.__datetime, self.__empty_tank, hubs, stopover_cost, constraints_list, self.airport_entry.get(), self.aircraft_file_entry.get(), self.currency_entry.get(), self.exchange_rate_entry.get(), self.output_entry.get())
class MainWindow(ttk.Frame): def __init__(self, master): # Variables self.url = StringVar() self.url_analyzer = None self.list_of_urls = [] self.url_dict = dict() # Main Window self.master = master self.master.iconbitmap(default=ico_path) self.master.title(string="URL Finder") self.master.minsize(width=300, height=375) self.master.maxsize(width=800, height=375) # Top Menu self.show_all = BooleanVar() self.file = Menu(self.master, tearoff=False) self.file.add_command(label="About", command=self.display_about) self.file.add_command(label="Exit", command=self.master.quit) self.edit = Menu(self.master, tearoff=False) self.edit.add_checkbutton(label="Show All", variable=self.show_all, command=self.update_list) self.menubar = Menu(self.master) self.menubar.add_cascade(label="File", menu=self.file) self.menubar.add_cascade(label="Edit", menu=self.edit) self.master.config(menu=self.menubar) # Right-click menu for entry widget self.right_click_entry = Menu(self.master, tearoff=False) self.right_click_entry.add_command(label="Copy", command=self.copy_from_entry) self.right_click_entry.add_command(label="Paste", command=self.paste_to_entry) # Right-click menu for treeview self.right_click = Menu(self.master, tearoff=False) self.right_click.add_command(label="Copy", command=self.get_selected_url) # Frame containing text box and enter button self.top_frame = ttk.Frame(self.master) self.top_frame.columnconfigure(0, minsize=200, weight=10) self.top_frame.columnconfigure(1, minsize=100, weight=1) # Frame containing urls and scrollbar self.bottom_frame = ttk.Frame(self.master) self.bottom_frame.columnconfigure(0, minsize=260, weight=1000) self.bottom_frame.columnconfigure(1, minsize=25, weight=1) # Url entry box and enter button self.entry = ttk.Entry(self.top_frame, textvariable=self.url) self.entry.bind('<Return>', self.on_enter) self.entry.bind('<Button-3>', self.entry_popup) self.enter = ttk.Button(self.top_frame, text="Find Urls", command=self.on_click) self.entry.grid(row=0, column=0, sticky=W+E, padx=5, pady=5) self.enter.grid(row=0, column=1, sticky=W+E, padx=5, pady=5) # Url list treeview self.list = ttk.Treeview(self.bottom_frame, height=15, columns=['percentage', 'domain']) self.list['show'] = 'headings' self.list.column('#0', width=0) self.list.column('percentage', width=30, minwidth=30, stretch=False) self.list.column('domain', width=250, minwidth=200, stretch=False) self.list.heading('percentage', text="%") self.list.heading('domain', text='Domain') self.list.bind('<Control-c>', self.ctrl_c) self.list.bind('<Button-3>', self.treeview_popup) self.list.grid(row=1, column=0, sticky=W+E+N+S, padx=5, pady=5) # Scrollbar widget self.scrollbar = ttk.Scrollbar(self.bottom_frame) self.scrollbar.grid(column=1, row=1, sticky=N+S+E+W) self.list.config(yscrollcommand=self.scrollbar.set) self.scrollbar.config(command=self.list.yview) self.top_frame.pack(fill=BOTH) self.bottom_frame.pack(fill=BOTH) def populate_list(self, url_percentage): del self.list_of_urls[:] for url, percentage in sorted(url_percentage.items(), key=lambda x: x[1]): if self.show_all.get() is True: row = (str(round(percentage)), url) self.list_of_urls.append(row) else: if percentage >= 1: row = (str(round(percentage)), url) self.list_of_urls.append(row) for row in self.list_of_urls: self.list.insert('', 0, values=row) def on_click(self): self.list.delete(*self.list.get_children()) self.enter.config(text="Running") url = self.url.get() t = threading.Thread(target=self.run_scan, args=(url,)) t.start() def run_scan(self, url): pm = ProcessManager(url) pm.start() count = 0 while pm.continue_scanning: time.sleep(1) count += 1 # This is to keep the system from reaching a timeout if count > 20: logging.info("Reached max timeout") pm.analyze_potential_urls() break self.url_dict = pm.url_percentage self.populate_list(pm.url_percentage) self.enter.config(text="Find Urls") def ctrl_c(self, event): self.get_selected_url() def add_to_clipboard(self, copy): self.master.clipboard_clear() self.master.clipboard_append(copy) def get_from_clipboad(self): return self.master.clipboard_get() def get_selected_url(self): curr_item = self.list.focus() item_dict = self.list.item(curr_item) self.add_to_clipboard(item_dict['values'][1]) def paste_to_entry(self): self.url.set(self.get_from_clipboad()) def copy_from_entry(self): self.add_to_clipboard(self.url.get()) def treeview_popup(self, event): item = self.list.identify_row(event.y) # Get Row self.list.selection_set(item) # Highlight Row self.list.focus(item) # Focus Row self.right_click.post(event.x_root, event.y_root) # Popup menu def entry_popup(self, event): self.right_click_entry.post(event.x_root, event.y_root) def on_enter(self, event): self.on_click() def update_list(self): self.list.delete(*self.list.get_children()) self.populate_list(self.url_dict) def display_about(self): about = "Supporting Url Finder Version: %s" % VERSION messagebox.showinfo("About", about)
class ConfigureGUI: def __init__(self): # # Main application window # self._root = Tk() self._root.title("Othello") self._root.focus() self._root.minsize(400, 250) self._root.columnconfigure(0, weight=1) self._root.rowconfigure(1, weight=1) # # Welcome label # welcome_frame = ttk.Frame(self._root, borderwidth=5) welcome_label = ttk.Label(welcome_frame, text="Welcome to GUI Othello!") welcome_frame.grid(row=0, column=0, sticky="ew") welcome_label.grid(row=0, column=0, padx=5, pady=5) welcome_frame.columnconfigure(0, weight=1) # # Main content (Configuration) # self._content = ttk.Frame(self._root) self._row = IntVar() row_label = ttk.Label(self._content, text="Number of Rows: ") row_picker = ttk.Combobox(self._content, state="readonly", textvariable=self._row, values=[4, 6, 8, 10, 12, 14, 16]) row_picker.set(8) self._col = IntVar() col_label = ttk.Label(self._content, text="Number of Columns: ") col_picker = ttk.Combobox(self._content, state="readonly", textvariable=self._col, values=[4, 6, 8, 10, 12, 14, 16]) col_picker.set(8) self._white_starts = BooleanVar() white_starts_label = ttk.Label(self._content, text="White starts: ") white_starts_picker = ttk.Combobox(self._content, state="readonly", textvariable=self._white_starts, values=[True, False]) white_starts_picker.current(1) self._classic_board_str = StringVar() classic_board_str_label = ttk.Label(self._content, text="Opening Board Style: ") classic_board_str_picker = ttk.Combobox(self._content, state="readonly", textvariable=self._classic_board_str) classic_board_str_picker["values"] = ["Classic (white starts in the top left)", "Inverted (black starts in the top left)"] classic_board_str_picker.set("Classic (white starts in the top left)") self._most_wins = BooleanVar() most_wins_label = ttk.Label(self._content, text="Most Pieces Wins: ") most_wins_picker = ttk.Combobox(self._content, state="readonly", textvariable=self._most_wins, values=[True, False]) most_wins_picker.current(0) self._content.grid(row=1, column=0, sticky="nsew") row_label.grid(row=0, column=0, sticky=(const.N, const.E), padx=5, pady=2) row_picker.grid(row=0, column=1, columnspan=2, sticky=(const.N, const.W, const.E), padx=2, pady=2) col_label.grid(row=1, column=0, sticky=(const.N, const.E), padx=5, pady=2) col_picker.grid(row=1, column=1, columnspan=2, sticky=(const.N, const.W, const.E), padx=2, pady=2) white_starts_label.grid(row=2, column=0, sticky=(const.N, const.E), padx=5, pady=2) white_starts_picker.grid(row=2, column=1, columnspan=2, sticky=(const.N, const.W, const.E), padx=2, pady=2) classic_board_str_label.grid(row=3, column=0, sticky=(const.N, const.E), padx=5, pady=2) classic_board_str_picker.grid(row=3, column=1, columnspan=2, sticky=(const.N, const.W, const.E), padx=2, pady=2) most_wins_label.grid(row=4, column=0, sticky=(const.N, const.E), padx=5, pady=2) most_wins_picker.grid(row=4, column=1, columnspan=2, sticky=(const.N, const.W, const.E), padx=2, pady=2) self._content.columnconfigure(0, minsize=70) self._content.columnconfigure(1, weight=1, minsize=50) self._content.columnconfigure(2, weight=1, minsize=50) self._content.rowconfigure(0, weight=1, minsize=30) self._content.rowconfigure(1, weight=1, minsize=30) self._content.rowconfigure(2, weight=1, minsize=30) self._content.rowconfigure(3, weight=1, minsize=30) self._content.rowconfigure(4, weight=1, minsize=30) # # Play/Quit buttons frame # play_frame = ttk.Frame(self._root, borderwidth=5) play = ttk.Button(play_frame, text="Play", command=self._press_play) cancel = ttk.Button(play_frame, text="Quit", command=exit) play_frame.grid(row=2, column=0, sticky="nsew") play.grid(row=0, column=0, sticky=(const.N, const.S, const.E), padx=5, pady=2) cancel.grid(row=0, column=1, sticky=(const.N, const.S, const.W), padx=5, pady=2) play_frame.columnconfigure(0, weight=1) play_frame.columnconfigure(1, weight=1) def _press_play(self): self._root.destroy() self.play = True def start(self) -> None: self._root.mainloop() if not self.play: exit() def getOthello(self) -> Othello: return Othello(self._row.get(), self._col.get(), self._white_starts.get(), True if (self._classic_board_str.get() == "Classic (white starts in the top left)") else False, self._most_wins.get())
class FrameSpreadsheetDataset(FrameCustomFileDataset): """ Holds an instance of, and visually represents, a spreadsheet dataset. See qal.dataset.spreadsheet.SpreadsheetDataset """ def __init__(self, _master, _dataset=None, _relief=None, _is_destination=None): super(FrameSpreadsheetDataset, self).__init__(_master, _dataset, _relief, _is_destination=_is_destination) if _dataset is None: self.dataset = SpreadsheetDataset() def on_select(self): """Brings up a selector dialog, prompting the user to select a file, the relative path if the file is then saved to the filename property. Also, the base path is set. """ self.select_file(_default_extension=".xlsx", _file_types=[('.xlsx files', '.xlsx'), ('all files', '.*')]) def init_widgets(self): # file selector self.btn_file_select = Button(self, text="Select file", command=self.on_select) self.btn_file_select.grid(column=0, row=0, columnspan=2) # filename self.filename, self.e_filename, self.l_filename = make_entry(self, "File name: ", 1) # delimiter self.delimiter, self.e_delimiter, self.l_delimiter = make_entry(self, "Delimiter: ", 2) # has_header self.l_has_header = ttk.Label(self, text="Has header: ") self.l_has_header.grid(column=0, row=3, sticky=W) self.has_header = BooleanVar() self.e_has_header = ttk.Checkbutton(self, variable=self.has_header) self.e_has_header.grid(column=1, row=3, sticky=W) # sheet_name self.sheet_name, self.e_sheet_name, self.l_sheet_name = make_entry(self, "Sheet name: ", 4) # x_offset self.x_offset, self.e_x_offset, self.l_x_offset = make_entry(self, "X offset: ", 5) # y_offset self.y_offset, self.e_y_offset, self.l_y_offset = make_entry(self, "Y offset: ", 6) def read_from_dataset(self): super(FrameSpreadsheetDataset, self).read_from_dataset() self.filename.set(empty_when_none(self.dataset.filename)) self.has_header.set(bool_to_binary_int(self.dataset.has_header)) self.sheet_name.set(empty_when_none(self.dataset.sheet_name)) self.x_offset.set(empty_when_none(self.dataset.x_offset)) self.y_offset.set(empty_when_none(self.dataset.y_offset)) def write_to_dataset(self): super(FrameSpreadsheetDataset, self).write_to_dataset() if self.dataset is None: self.dataset = SpreadsheetDataset() self.dataset.filename = self.filename.get() self.dataset.delimiter = self.delimiter.get() self.dataset.has_header = binary_int_to_bool(self.has_header.get()) self.dataset.sheet_name = self.sheet_name.get() if self.x_offset.get() == "": self.dataset.x_offset = None else: self.dataset.x_offset = int(self.x_offset.get()) if self.y_offset.get() == "": self.dataset.y_offset = None else: self.dataset.y_offset = int(self.y_offset.get()) def reload(self): self.notify_task("Load spreadsheet " + self.dataset.filename, 10) self.dataset.load() self.notify_task("Loaded spreadsheet " + self.dataset.filename + ".", 100) def get_possible_references(self, _force=None): if not self.dataset.field_names or _force == True: self.reload() self.references = self.dataset.field_names return self.dataset.field_names
class ViewRenderedGrid(ViewWinGrid.ViewGrid): def __init__(self, modelXbrl, tabWin, lang): super(ViewRenderedGrid, self).__init__(modelXbrl, tabWin, "Rendering", True, lang) self.newFactItemOptions = ModelInstanceObject.NewFactItemOptions(xbrlInstance=modelXbrl) self.factPrototypes = [] self.zOrdinateChoices = None # context menu Boolean vars self.options = self.modelXbrl.modelManager.cntlr.config.setdefault("viewRenderedGridOptions", {}) self.ignoreDimValidity = BooleanVar(value=self.options.setdefault("ignoreDimValidity",True)) self.xAxisChildrenFirst = BooleanVar(value=self.options.setdefault("xAxisChildrenFirst",True)) self.yAxisChildrenFirst = BooleanVar(value=self.options.setdefault("yAxisChildrenFirst",False)) def close(self): super(ViewRenderedGrid, self).close() if self.modelXbrl: for fp in self.factPrototypes: fp.clear() self.factPrototypes = None def loadTablesMenu(self): tblMenuEntries = {} tblRelSet = self.modelXbrl.relationshipSet("Table-rendering") for tblLinkroleUri in tblRelSet.linkRoleUris: for tableAxisArcrole in (XbrlConst.euTableAxis, XbrlConst.tableBreakdown, XbrlConst.tableBreakdown201301, XbrlConst.tableAxis2011): tblAxisRelSet = self.modelXbrl.relationshipSet(tableAxisArcrole, tblLinkroleUri) if tblAxisRelSet and len(tblAxisRelSet.modelRelationships) > 0: # table name modelRoleTypes = self.modelXbrl.roleTypes.get(tblLinkroleUri) if modelRoleTypes is not None and len(modelRoleTypes) > 0: roledefinition = modelRoleTypes[0].definition if roledefinition is None or roledefinition == "": roledefinition = os.path.basename(tblLinkroleUri) for table in tblAxisRelSet.rootConcepts: # add table to menu if there's any entry tblMenuEntries[roledefinition] = tblLinkroleUri break self.tablesMenu.delete(0, self.tablesMenuLength) self.tablesMenuLength = 0 self.tblELR = None for tblMenuEntry in sorted(tblMenuEntries.items()): tbl,elr = tblMenuEntry self.tablesMenu.add_command(label=tbl, command=lambda e=elr: self.view(viewTblELR=e)) self.tablesMenuLength += 1 if self.tblELR is None: self.tblELR = elr # start viewing first ELR def viewReloadDueToMenuAction(self, *args): if not self.blockMenuEvents: # update config (config saved when exiting) self.options["ignoreDimValidity"] = self.ignoreDimValidity.get() self.options["xAxisChildrenFirst"] = self.xAxisChildrenFirst.get() self.options["yAxisChildrenFirst"] = self.yAxisChildrenFirst.get() self.view() def view(self, viewTblELR=None, newInstance=None): startedAt = time.time() self.blockMenuEvents += 1 if newInstance is not None: self.modelXbrl = newInstance # a save operation has created a new instance to use subsequently clearZchoices = False if viewTblELR: # specific table selection self.tblELR = viewTblELR clearZchoices = True else: # first or subsequenct reloading (language, dimensions, other change) clearZchoices = self.zOrdinateChoices is None if clearZchoices: # also need first time initialization self.loadTablesMenu() # load menus (and initialize if first time viewTblELR = self.tblELR if not self.tblELR: return # no table to display if clearZchoices: self.zOrdinateChoices = {} # remove old widgets self.viewFrame.clearGrid() tblAxisRelSet, xTopStructuralNode, yTopStructuralNode, zTopStructuralNode = resolveAxesStructure(self, viewTblELR) if tblAxisRelSet: #print("tbl hdr width rowHdrCols {0}".format(self.rowHdrColWidth)) self.gridTblHdr.tblHdrWraplength = 200 # to adjust dynamically during configure callbacks self.gridTblHdr.tblHdrLabel = \ gridHdr(self.gridTblHdr, 0, 0, (self.modelTable.genLabel(lang=self.lang, strip=True) or # use table label, if any self.roledefinition), anchor="nw", #columnspan=(self.dataFirstCol - 1), #rowspan=(self.dataFirstRow), wraplength=200) # in screen units #wraplength=sum(self.rowHdrColWidth)) # in screen units zAspects = defaultdict(set) self.zAxis(1, zTopStructuralNode, zAspects, clearZchoices) xStructuralNodes = [] self.xAxis(self.dataFirstCol, self.colHdrTopRow, self.colHdrTopRow + self.colHdrRows - 1, xTopStructuralNode, xStructuralNodes, self.xAxisChildrenFirst.get(), True, True) self.yAxis(1, self.dataFirstRow, yTopStructuralNode, self.yAxisChildrenFirst.get(), True, True) for fp in self.factPrototypes: # dereference prior facts if fp is not None: fp.clear() self.factPrototypes = [] self.bodyCells(self.dataFirstRow, yTopStructuralNode, xStructuralNodes, zAspects, self.yAxisChildrenFirst.get()) # data cells #print("body cells done") self.modelXbrl.profileStat("viewTable_" + os.path.basename(viewTblELR), time.time() - startedAt) #self.gridView.config(scrollregion=self.gridView.bbox(constants.ALL)) self.blockMenuEvents -= 1 def zAxis(self, row, zStructuralNode, zAspects, clearZchoices): if zStructuralNode is not None: gridBorder(self.gridColHdr, self.dataFirstCol, row, TOPBORDER, columnspan=2) gridBorder(self.gridColHdr, self.dataFirstCol, row, LEFTBORDER) gridBorder(self.gridColHdr, self.dataFirstCol, row, RIGHTBORDER, columnspan=2) label = zStructuralNode.header(lang=self.lang) hdr = gridHdr(self.gridColHdr, self.dataFirstCol, row, label, anchor="w", columnspan=2, wraplength=200, # in screen units objectId=zStructuralNode.objectId(), onClick=self.onClick) if zStructuralNode.choiceStructuralNodes: # combo box valueHeaders = [''.ljust(zChoiceStructuralNode.indent * 4) + # indent if nested choices (zChoiceStructuralNode.header(lang=self.lang) or '') for zChoiceStructuralNode in zStructuralNode.choiceStructuralNodes] combobox = gridCombobox( self.gridColHdr, self.dataFirstCol + 2, row, values=valueHeaders, selectindex=zStructuralNode.choiceNodeIndex, columnspan=2, comboboxselected=self.onComboBoxSelected) combobox.zStructuralNode = zStructuralNode combobox.zChoiceOrdIndex = row - 1 combobox.objectId = hdr.objectId = zStructuralNode.objectId() gridBorder(self.gridColHdr, self.dataFirstCol + 3, row, RIGHTBORDER) if zStructuralNode.childStructuralNodes: for zStructuralNode in zStructuralNode.childStructuralNodes: self.zAxis(row + 1, zStructuralNode, zAspects, clearZchoices) else: # nested-nost element, aspects process inheritance for aspect in aspectModels[self.aspectModel]: for ruleAspect in aspectRuleAspects.get(aspect, (aspect,)): if zStructuralNode.hasAspect(ruleAspect): #implies inheriting from other z axes if ruleAspect == Aspect.DIMENSIONS: for dim in (zStructuralNode.aspectValue(Aspect.DIMENSIONS) or emptyList): zAspects[dim].add(zStructuralNode) else: zAspects[ruleAspect].add(zStructuralNode) def onComboBoxSelected(self, *args): combobox = args[0].widget self.zOrdinateChoices[combobox.zStructuralNode._definitionNode] = \ combobox.zStructuralNode.choiceNodeIndex = combobox.valueIndex self.view() # redraw grid def xAxis(self, leftCol, topRow, rowBelow, xParentStructuralNode, xStructuralNodes, childrenFirst, renderNow, atTop): if xParentStructuralNode is not None: parentRow = rowBelow noDescendants = True rightCol = leftCol widthToSpanParent = 0 sideBorder = not xStructuralNodes if atTop and sideBorder and childrenFirst: gridBorder(self.gridColHdr, self.dataFirstCol, 1, LEFTBORDER, rowspan=self.dataFirstRow) for xStructuralNode in xParentStructuralNode.childStructuralNodes: if not xStructuralNode.isRollUp: noDescendants = False rightCol, row, width, leafNode = self.xAxis(leftCol, topRow + 1, rowBelow, xStructuralNode, xStructuralNodes, # nested items before totals childrenFirst, childrenFirst, False) if row - 1 < parentRow: parentRow = row - 1 #if not leafNode: # rightCol -= 1 nonAbstract = not xStructuralNode.isAbstract if nonAbstract: width += 100 # width for this label, in screen units widthToSpanParent += width label = xStructuralNode.header(lang=self.lang, returnGenLabel=isinstance(xStructuralNode.definitionNode, (ModelClosedDefinitionNode, ModelEuAxisCoord))) if childrenFirst: thisCol = rightCol sideBorder = RIGHTBORDER else: thisCol = leftCol sideBorder = LEFTBORDER if renderNow: columnspan = (rightCol - leftCol + (1 if nonAbstract else 0)) gridBorder(self.gridColHdr, leftCol, topRow, TOPBORDER, columnspan=columnspan) gridBorder(self.gridColHdr, leftCol, topRow, sideBorder, columnspan=columnspan, rowspan=(rowBelow - topRow + 1) ) gridHdr(self.gridColHdr, leftCol, topRow, label if label else " ", anchor="center", columnspan=(rightCol - leftCol + (1 if nonAbstract else 0)), rowspan=(row - topRow + 1) if leafNode else 1, wraplength=width, # screen units objectId=xStructuralNode.objectId(), onClick=self.onClick) if nonAbstract: for i, role in enumerate(self.colHdrNonStdRoles): gridBorder(self.gridColHdr, thisCol, self.dataFirstRow - len(self.colHdrNonStdRoles) + i, TOPBORDER) gridBorder(self.gridColHdr, thisCol, self.dataFirstRow - len(self.colHdrNonStdRoles) + i, sideBorder) gridHdr(self.gridColHdr, thisCol, self.dataFirstRow - len(self.colHdrNonStdRoles) + i, xStructuralNode.header(role=role, lang=self.lang), anchor="center", wraplength=100, # screen units objectId=xStructuralNode.objectId(), onClick=self.onClick) ''' was if self.colHdrDocRow: gridBorder(self.gridColHdr, thisCol, self.dataFirstRow - 1 - self.rowHdrCodeCol, TOPBORDER) gridBorder(self.gridColHdr, thisCol, self.dataFirstRow - 1 - self.rowHdrCodeCol, sideBorder) gridHdr(self.gridColHdr, thisCol, self.dataFirstRow - 1 - self.rowHdrCodeCol, xStructuralNode.header(role="http://www.xbrl.org/2008/role/documentation", lang=self.lang), anchor="center", wraplength=100, # screen units objectId=xStructuralNode.objectId(), onClick=self.onClick) if self.colHdrCodeRow: gridBorder(self.gridColHdr, thisCol, self.dataFirstRow - 1, TOPBORDER) gridBorder(self.gridColHdr, thisCol, self.dataFirstRow - 1, sideBorder) gridHdr(self.gridColHdr, thisCol, self.dataFirstRow - 1, xStructuralNode.header(role="http://www.eurofiling.info/role/2010/coordinate-code"), anchor="center", wraplength=100, # screen units objectId=xStructuralNode.objectId(), onClick=self.onClick) ''' gridBorder(self.gridColHdr, thisCol, self.dataFirstRow - 1, BOTTOMBORDER) xStructuralNodes.append(xStructuralNode) if nonAbstract: rightCol += 1 if renderNow and not childrenFirst: self.xAxis(leftCol + (1 if nonAbstract else 0), topRow + 1, rowBelow, xStructuralNode, xStructuralNodes, childrenFirst, True, False) # render on this pass leftCol = rightCol if atTop and sideBorder and not childrenFirst: gridBorder(self.gridColHdr, rightCol - 1, 1, RIGHTBORDER, rowspan=self.dataFirstRow) return (rightCol, parentRow, widthToSpanParent, noDescendants) def yAxis(self, leftCol, row, yParentStructuralNode, childrenFirst, renderNow, atLeft): if yParentStructuralNode is not None: nestedBottomRow = row if atLeft: gridBorder(self.gridRowHdr, self.rowHdrCols + len(self.rowHdrNonStdRoles), # was: self.rowHdrDocCol + self.rowHdrCodeCol, self.dataFirstRow, RIGHTBORDER, rowspan=self.dataRows) gridBorder(self.gridRowHdr, 1, self.dataFirstRow + self.dataRows - 1, BOTTOMBORDER, columnspan=(self.rowHdrCols + len(self.rowHdrNonStdRoles))) # was: self.rowHdrDocCol + self.rowHdrCodeCol)) for yStructuralNode in yParentStructuralNode.childStructuralNodes: if not yStructuralNode.isRollUp: nestRow, nextRow = self.yAxis(leftCol + 1, row, yStructuralNode, # nested items before totals childrenFirst, childrenFirst, False) isAbstract = (yStructuralNode.isAbstract or (yStructuralNode.childStructuralNodes and not isinstance(yStructuralNode.definitionNode, (ModelClosedDefinitionNode, ModelEuAxisCoord)))) isNonAbstract = not isAbstract label = yStructuralNode.header(lang=self.lang, returnGenLabel=isinstance(yStructuralNode.definitionNode, (ModelClosedDefinitionNode, ModelEuAxisCoord))) topRow = row if childrenFirst and isNonAbstract: row = nextRow if renderNow: columnspan = self.rowHdrCols - leftCol + 1 if isNonAbstract or nextRow == row else None gridBorder(self.gridRowHdr, leftCol, topRow, LEFTBORDER, rowspan=(nestRow - topRow + 1) ) gridBorder(self.gridRowHdr, leftCol, topRow, TOPBORDER, columnspan=(1 if childrenFirst and nextRow > row else columnspan)) if childrenFirst and row > topRow: gridBorder(self.gridRowHdr, leftCol + 1, row, TOPBORDER, columnspan=(self.rowHdrCols - leftCol)) depth = yStructuralNode.depth gridHdr(self.gridRowHdr, leftCol, row, label if label is not None else " ", anchor=("w" if isNonAbstract or nestRow == row else "center"), columnspan=columnspan, rowspan=(nestRow - row if isAbstract else None), # wraplength is in screen units wraplength=(self.rowHdrColWidth[depth] if isAbstract else self.rowHdrWrapLength - sum(self.rowHdrColWidth[0:depth])), #minwidth=self.rowHdrColWidth[leftCol], minwidth=(16 if isNonAbstract and nextRow > topRow else None), objectId=yStructuralNode.objectId(), onClick=self.onClick) if isNonAbstract: for i, role in enumerate(self.rowHdrNonStdRoles): isCode = "code" in role docCol = self.dataFirstCol - len(self.rowHdrNonStdRoles) + i gridBorder(self.gridRowHdr, docCol, row, TOPBORDER) gridBorder(self.gridRowHdr, docCol, row, LEFTBORDER) gridHdr(self.gridRowHdr, docCol, row, yStructuralNode.header(role=role, lang=self.lang), anchor="c" if isCode else "w", wraplength=40 if isCode else 100, # screen units objectId=yStructuralNode.objectId(), onClick=self.onClick) ''' was: if self.rowHdrDocCol: docCol = self.dataFirstCol - 1 - self.rowHdrCodeCol gridBorder(self.gridRowHdr, docCol, row, TOPBORDER) gridBorder(self.gridRowHdr, docCol, row, LEFTBORDER) gridHdr(self.gridRowHdr, docCol, row, yStructuralNode.header(role="http://www.xbrl.org/2008/role/documentation", lang=self.lang), anchor="w", wraplength=100, # screen units objectId=yStructuralNode.objectId(), onClick=self.onClick) if self.rowHdrCodeCol: codeCol = self.dataFirstCol - 1 gridBorder(self.gridRowHdr, codeCol, row, TOPBORDER) gridBorder(self.gridRowHdr, codeCol, row, LEFTBORDER) gridHdr(self.gridRowHdr, codeCol, row, yStructuralNode.header(role="http://www.eurofiling.info/role/2010/coordinate-code"), anchor="center", wraplength=40, # screen units objectId=yStructuralNode.objectId(), onClick=self.onClick) # gridBorder(self.gridRowHdr, leftCol, self.dataFirstRow - 1, BOTTOMBORDER) ''' if isNonAbstract: row += 1 elif childrenFirst: row = nextRow if nestRow > nestedBottomRow: nestedBottomRow = nestRow + (isNonAbstract and not childrenFirst) if row > nestedBottomRow: nestedBottomRow = row #if renderNow and not childrenFirst: # dummy, row = self.yAxis(leftCol + 1, row, yStructuralNode, childrenFirst, True, False) # render on this pass if not childrenFirst: dummy, row = self.yAxis(leftCol + 1, row, yStructuralNode, childrenFirst, renderNow, False) # render on this pass return (nestedBottomRow, row) def bodyCells(self, row, yParentStructuralNode, xStructuralNodes, zAspects, yChildrenFirst): if yParentStructuralNode is not None: rendrCntx = getattr(self.modelXbrl, "rendrCntx", None) # none for EU 2010 tables dimDefaults = self.modelXbrl.qnameDimensionDefaults for yStructuralNode in yParentStructuralNode.childStructuralNodes: if yChildrenFirst: row = self.bodyCells(row, yStructuralNode, xStructuralNodes, zAspects, yChildrenFirst) if not yStructuralNode.isAbstract: yAspects = defaultdict(set) for aspect in aspectModels[self.aspectModel]: for ruleAspect in aspectRuleAspects.get(aspect, (aspect,)): if yStructuralNode.hasAspect(ruleAspect): if ruleAspect == Aspect.DIMENSIONS: for dim in (yStructuralNode.aspectValue(Aspect.DIMENSIONS) or emptyList): yAspects[dim].add(yStructuralNode) else: yAspects[ruleAspect].add(yStructuralNode) gridSpacer(self.gridBody, self.dataFirstCol, row, LEFTBORDER) # data for columns of row ignoreDimValidity = self.ignoreDimValidity.get() for i, xStructuralNode in enumerate(xStructuralNodes): xAspects = defaultdict(set) for aspect in aspectModels[self.aspectModel]: for ruleAspect in aspectRuleAspects.get(aspect, (aspect,)): if xStructuralNode.hasAspect(ruleAspect): if ruleAspect == Aspect.DIMENSIONS: for dim in (xStructuralNode.aspectValue(Aspect.DIMENSIONS) or emptyList): xAspects[dim].add(xStructuralNode) else: xAspects[ruleAspect].add(xStructuralNode) cellAspectValues = {} matchableAspects = set() for aspect in _DICT_SET(xAspects.keys()) | _DICT_SET(yAspects.keys()) | _DICT_SET(zAspects.keys()): aspectValue = inheritedAspectValue(self, aspect, xAspects, yAspects, zAspects, xStructuralNode, yStructuralNode) if dimDefaults.get(aspect) != aspectValue: # don't include defaulted dimensions cellAspectValues[aspect] = aspectValue matchableAspects.add(aspectModelAspect.get(aspect,aspect)) #filterable aspect from rule aspect cellDefaultedDims = _DICT_SET(dimDefaults) - _DICT_SET(cellAspectValues.keys()) priItemQname = cellAspectValues.get(Aspect.CONCEPT) concept = self.modelXbrl.qnameConcepts.get(priItemQname) conceptNotAbstract = concept is None or not concept.isAbstract from arelle.ValidateXbrlDimensions import isFactDimensionallyValid value = None objectId = None justify = None fp = FactPrototype(self, cellAspectValues) if conceptNotAbstract: # reduce set of matchable facts to those with pri item qname and have dimension aspects facts = self.modelXbrl.factsByQname[priItemQname] if priItemQname else self.modelXbrl.factsInInstance for aspect in matchableAspects: # trim down facts with explicit dimensions match or just present if isinstance(aspect, QName): aspectValue = cellAspectValues.get(aspect, None) if isinstance(aspectValue, ModelDimensionValue): if aspectValue.isExplicit: dimMemQname = aspectValue.memberQname # match facts with this explicit value else: dimMemQname = None # match facts that report this dimension elif isinstance(aspectValue, QName): dimMemQname = aspectValue # match facts that have this explicit value else: dimMemQname = None # match facts that report this dimension facts = facts & self.modelXbrl.factsByDimMemQname(aspect, dimMemQname) for fact in facts: if (all(aspectMatches(rendrCntx, fact, fp, aspect) for aspect in matchableAspects) and all(fact.context.dimMemberQname(dim,includeDefaults=True) in (dimDefaults[dim], None) for dim in cellDefaultedDims)): if yStructuralNode.hasValueExpression(xStructuralNode): value = yStructuralNode.evalValueExpression(fact, xStructuralNode) else: value = fact.effectiveValue objectId = fact.objectId() justify = "right" if fact.isNumeric else "left" break if (conceptNotAbstract and (value is not None or ignoreDimValidity or isFactDimensionallyValid(self, fp))): if objectId is None: objectId = "f{0}".format(len(self.factPrototypes)) self.factPrototypes.append(fp) # for property views gridCell(self.gridBody, self.dataFirstCol + i, row, value, justify=justify, width=12, # width is in characters, not screen units objectId=objectId, onClick=self.onClick) else: fp.clear() # dereference gridSpacer(self.gridBody, self.dataFirstCol + i, row, CENTERCELL) gridSpacer(self.gridBody, self.dataFirstCol + i, row, RIGHTBORDER) gridSpacer(self.gridBody, self.dataFirstCol + i, row, BOTTOMBORDER) row += 1 if not yChildrenFirst: row = self.bodyCells(row, yStructuralNode, xStructuralNodes, zAspects, yChildrenFirst) return row def onClick(self, event): objId = event.widget.objectId if objId and objId[0] == "f": viewableObject = self.factPrototypes[int(objId[1:])] else: viewableObject = objId self.modelXbrl.viewModelObject(viewableObject) self.modelXbrl.modelManager.cntlr.currentView = self def cellEnter(self, *args): self.blockSelectEvent = 0 self.modelXbrl.modelManager.cntlr.currentView = self def cellLeave(self, *args): self.blockSelectEvent = 1 def cellSelect(self, *args): if self.blockSelectEvent == 0 and self.blockViewModelObject == 0: self.blockViewModelObject += 1 #self.modelXbrl.viewModelObject(self.nodeToObjectId[self.treeView.selection()[0]]) #self.modelXbrl.viewModelObject(self.treeView.selection()[0]) self.blockViewModelObject -= 1 def viewModelObject(self, modelObject): if self.blockViewModelObject == 0: self.blockViewModelObject += 1 ''' try: if isinstance(modelObject, ModelObject.ModelRelationship): conceptId = modelObject.toModelObject.objectId() elif isinstance(modelObject, ModelObject.ModelFact): conceptId = self.modelXbrl.qnameConcepts[modelObject.qname].objectId() else: conceptId = modelObject.objectId() #node = self.objectIdToNode[conceptId] node = conceptId if self.treeView.exists(node): self.treeView.see(node) self.treeView.selection_set(node) except KeyError: self.treeView.selection_set(()) ''' self.blockViewModelObject -= 1 def saveInstance(self, newFilename=None): if (not self.newFactItemOptions.entityIdentScheme or # not initialized yet not self.newFactItemOptions.entityIdentValue or not self.newFactItemOptions.startDateDate or not self.newFactItemOptions.endDateDate): if not getNewFactItemOptions(self.modelXbrl.modelManager.cntlr, self.newFactItemOptions): return # new instance not set # newFilename = None # only used when a new instance must be created if self.modelXbrl.modelDocument.type != ModelDocument.Type.INSTANCE and newFilename is None: newFilename = self.modelXbrl.modelManager.cntlr.fileSave(view=self, fileType="xbrl") if not newFilename: return # saving cancelled # continue saving in background thread = threading.Thread(target=lambda: self.backgroundSaveInstance(newFilename)) thread.daemon = True thread.start() def backgroundSaveInstance(self, newFilename=None): cntlr = self.modelXbrl.modelManager.cntlr if newFilename and self.modelXbrl.modelDocument.type != ModelDocument.Type.INSTANCE: self.modelXbrl.modelManager.showStatus(_("creating new instance {0}").format(os.path.basename(newFilename))) self.modelXbrl.modelManager.cntlr.waitForUiThreadQueue() # force status update self.modelXbrl.createInstance(newFilename) # creates an instance as this modelXbrl's entrypoing instance = self.modelXbrl cntlr.showStatus(_("Saving {0}").format(instance.modelDocument.basename)) cntlr.waitForUiThreadQueue() # force status update newCntx = ModelXbrl.AUTO_LOCATE_ELEMENT newUnit = ModelXbrl.AUTO_LOCATE_ELEMENT # check user keyed changes for bodyCell in self.gridBody.winfo_children(): if isinstance(bodyCell, gridCell) and bodyCell.isChanged: value = bodyCell.value objId = bodyCell.objectId if objId: if objId[0] == "f": factPrototypeIndex = int(objId[1:]) factPrototype = self.factPrototypes[factPrototypeIndex] concept = factPrototype.concept entityIdentScheme = self.newFactItemOptions.entityIdentScheme entityIdentValue = self.newFactItemOptions.entityIdentValue periodType = factPrototype.concept.periodType periodStart = self.newFactItemOptions.startDateDate if periodType == "duration" else None periodEndInstant = self.newFactItemOptions.endDateDate qnameDims = factPrototype.context.qnameDims prevCntx = instance.matchContext( entityIdentScheme, entityIdentValue, periodType, periodStart, periodEndInstant, qnameDims, [], []) if prevCntx is not None: cntxId = prevCntx.id else: # need new context newCntx = instance.createContext(entityIdentScheme, entityIdentValue, periodType, periodStart, periodEndInstant, concept.qname, qnameDims, [], [], afterSibling=newCntx) cntxId = newCntx.id # new context if concept.isNumeric: if concept.isMonetary: unitMeasure = qname(XbrlConst.iso4217, self.newFactItemOptions.monetaryUnit) unitMeasure.prefix = "iso4217" # want to save with a recommended prefix decimals = self.newFactItemOptions.monetaryDecimals elif concept.isShares: unitMeasure = XbrlConst.qnXbrliShares decimals = self.newFactItemOptions.nonMonetaryDecimals else: unitMeasure = XbrlConst.qnXbrliPure decimals = self.newFactItemOptions.nonMonetaryDecimals prevUnit = instance.matchUnit([unitMeasure],[]) if prevUnit is not None: unitId = prevUnit.id else: newUnit = instance.createUnit([unitMeasure],[], afterSibling=newUnit) unitId = newUnit.id attrs = [("contextRef", cntxId)] if concept.isNumeric: attrs.append(("unitRef", unitId)) attrs.append(("decimals", decimals)) value = Locale.atof(self.modelXbrl.locale, value, str.strip) newFact = instance.createFact(concept.qname, attributes=attrs, text=value) bodyCell.objectId = newFact.objectId() # switch cell to now use fact ID if self.factPrototypes[factPrototypeIndex] is not None: self.factPrototypes[factPrototypeIndex].clear() self.factPrototypes[factPrototypeIndex] = None #dereference fact prototype else: # instance fact, not prototype fact = self.modelXbrl.modelObject(objId) if fact.concept.isNumeric: value = Locale.atof(self.modelXbrl.locale, value, str.strip) if fact.value != value: if fact.concept.isNumeric and fact.isNil != (not value): fact.isNil = not value if value: # had been nil, now it needs decimals fact.decimals = (self.newFactItemOptions.monetaryDecimals if fact.concept.isMonetary else self.newFactItemOptions.nonMonetaryDecimals) fact.text = value XmlValidate.validate(instance, fact) bodyCell.isChanged = False # clear change flag instance.saveInstance(newFilename) # may override prior filename for instance from main menu cntlr.showStatus(_("Saved {0}").format(instance.modelDocument.basename), clearAfter=3000)
class ReplicatorMain(VerticalScrolledFrame): """The main class for the GUI of the application""" merge = None """This is the merge object of the application, it holds all settings for the merge operation""" filename = None """The name of the file containing the merge definition""" fr_src_dataset = None """The fram of the source dataset, contains a FrameCustomDataset descendant""" fr_dest_dataset = None """The fram of the source dataset, contains a FrameCustomDataset descendant""" suppress_errors = None """Do not show any errors""" _row_index = None """The current row in the dataset""" curr_mapping_frame = None """The currently selected mapping frame""" def __init__(self, _merge=None, _filename=None, *args, **kw): self.parent = Tk() # Init oneself super(ReplicatorMain, self).__init__(self.parent, bd=1, relief=SUNKEN, *args, **kw) self.grid(stick=(E, W, N, S)) self.suppress_errors = None self.merge = _merge self.filename = _filename self.fr_src_dataset = None self.fr_dest_dataset = None self.grid() self.ip_address = StringVar() self._row_index = 0 self.init_GUI() if _filename is not None and _merge is not None: # _merge._load_datasets() self._merge_to_gui() self.parent.columnconfigure(0, weight=1) self.parent.rowconfigure(0, weight=1) self.resize() self.parent.mainloop() def resize(self): """ Resize the window, set the width what the internal windows need. """ self._canvas.update_idletasks() self.fr_top_right.update_idletasks() self._canvas.config(width=self.interior.winfo_reqwidth() + 1, height=self.interior.winfo_reqheight()) def on_dataset_columns_change(self, *args): # Columns have changed; force reload columns from structure self.fr_src_dataset.get_possible_references(True) self.fr_dest_dataset.get_possible_references(True) for curr_mapping in self.g_mappings.items: curr_mapping.fr_item.reload_references() def notify_task(self, _task, _progress): """Override as this is the top widget""" self.fr_Status_Bar.update_task(_task, _progress) def notify_messagebox(self, _title, _message, _kind=None): """Override as this is the top class, default is error.""" if self.suppress_errors is None: if _kind == "message": messagebox.showinfo(_title, _message) elif _kind == "warning": messagebox.showwarning(_title, _message) else: messagebox.showerror(_title, _message) def on_post_merge_sql(self, *args): # Show post-merge-SQL dialog _wdw = Toplevel() _wdw.geometry('+400+400') _wdw.e = TextExtension(_wdw, textvariable=self.post_execute_sql) _wdw.e.pack() _wdw.e.focus_set() _wdw.transient(self.parent) _wdw.grab_set() self.parent.wait_window(_wdw) _wdw.e.unhook() del (_wdw) def on_src_connect(self, *args): """Event handler for when the source connection is set""" self.fr_mapping.src_dal = self.fr_dataset_src.dal def on_dest_connect(self, *args): """Event handler for when the destination connection is set""" self.fr_mapping.dest_dal = self.fr_dataset_dest.dal def init_GUI(self): """Init main application GUI""" print("Initializing GUI...", end="") self.parent.title("Optimal Sync - Move that data - a part of Optimal BPM") self.interior.notify_task = self.notify_task self.interior.notify_messagebox = self.notify_messagebox self.fr_top = BPMFrame(self.interior) self.fr_top.pack(side=TOP, fill=BOTH, expand=1) self.fr_top_left = BPMFrame(self.fr_top) self.fr_top_left.pack(side=LEFT, fill=BOTH, expand=1) self.fr_rw = BPMFrame(self.fr_top_left) self.fr_rw.pack(side=TOP, fill=X) self.btn_Load_json_json = ttk.Button(self.fr_rw, text="Load", command=self.on_load_json) self.btn_Load_json_json.pack(side=LEFT) self.btn_Save_json = ttk.Button(self.fr_rw, text="Save", command=self.on_save_json) self.btn_Save_json.pack(side=LEFT) self.fr_subnet_sql = BPMFrame(self.fr_rw) self.l_ip = ttk.Label(self.fr_subnet_sql, text="IP(for subnet scan):") self.l_ip.pack(side=LEFT) self.ip_address.set("192.168.0.1") self.e_ip_address = ttk.Entry(self.fr_subnet_sql, textvariable=self.ip_address) self.e_ip_address.pack(side=RIGHT) self.fr_subnet_sql.pack(side=RIGHT) # datasets self.fr_datasets = BPMFrame(self.fr_top_left) self.fr_datasets.pack(side=TOP) self.sel_src_dataset_type = Selector(_master=self.fr_datasets, _values=('RDBMS', 'XPath', 'Flatfile', 'Spreadsheet'), _caption="Sources dataset type:", _onchange=self.on_src_dataset_type_change) self.sel_src_dataset_type.grid(column=0, row=0, sticky=W) self.sel_dest_dataset_type = Selector(_master=self.fr_datasets, _values=('RDBMS', 'XPath', 'Flatfile', 'Spreadsheet'), _caption="Destination dataset type:", _onchange=self.on_dest_dataset_type_change) self.sel_dest_dataset_type.grid(column=1, row=0, sticky=W) # Mappings self.fr_mapping_header = BPMFrame(self.fr_top_left) self.fr_mapping_header.pack(side=TOP) self.l_mapping = ttk.Label(self.fr_mapping_header, text="Mappings:") self.l_mapping.pack(side=TOP) self.fr_mapping_header_nav = BPMFrame(self.fr_mapping_header) self.fr_mapping_header_nav.pack(side=BOTTOM) self.btn_first = Button(self.fr_mapping_header_nav, text="<<", command=self.on_first) self.btn_first.pack(side=LEFT) self.btn_prev = Button(self.fr_mapping_header_nav, text="<", command=self.on_prev) self.btn_prev.pack(side=LEFT) self.btn_reload = Button(self.fr_mapping_header_nav, text="Reload data", command=self.on_reload_data) self.btn_reload.pack(side=LEFT) self.btn_next = Button(self.fr_mapping_header_nav, text=">", command=self.on_next) self.btn_next.pack(side=LEFT) self.btn_last = Button(self.fr_mapping_header_nav, text=">>", command=self.on_last) self.btn_last.pack(side=LEFT) self.g_mappings = FrameList(self.fr_top_left, _detail_key_text="Transformations >>", bd=1, relief=SUNKEN) self.g_mappings.pack(side=TOP, fill=X) self.g_mappings.on_delete = self.mappings_do_on_delete self.g_mappings.on_move_up = self.mappings_do_on_move_up self.g_mappings.on_move_down = self.mappings_do_on_move_down self.g_mappings.on_detail = self.mappings_do_on_detail self.btn_append_mapping = Button(self.fr_top_left, text="Append mapping", command=self.on_append_mapping) self.btn_append_mapping.pack(side=TOP) # Transformation self.fr_top_right = BPMFrame(self.fr_top) self.fr_top_right.pack(side=RIGHT, fill=Y) self.l_transformations = ttk.Label(self.fr_top_right, text="Transformations") self.l_transformations.pack(side=TOP) self.g_transformations = FrameList(self.fr_top_right, bd=1, relief=SUNKEN) self.g_transformations.pack(fill=BOTH, expand=1) self.g_transformations.on_delete = self.transformations_do_on_delete self.g_transformations.on_move_up = self.transformations_do_on_move_up self.g_transformations.on_move_down = self.transformations_do_on_move_down self.fr_append_transformation = ttk.Frame(self.fr_top_right) self.fr_append_transformation.pack(side=BOTTOM) self.btn_append_transformation = Button(self.fr_append_transformation, text="Append Transformation", command=self.on_append_transformation) self.btn_append_transformation.pack(side=LEFT) self.transformation_append_type = StringVar() self.sel_transformation_append_type = ttk.Combobox(self.fr_append_transformation, textvariable=self.transformation_append_type, state='readonly') self.sel_transformation_append_type['values'] = ["Replace", "Replace regex", "Cast", "If empty", "Trim"] self.sel_transformation_append_type.current(0) self.sel_transformation_append_type.pack(side=LEFT, fill=X) # Merge preview self.fr_Preview = ttk.Frame(self.fr_top_left) self.fr_Preview.pack(side=TOP, fill=BOTH, expand=1) self.fr_merge_actions = ttk.Frame(self.fr_Preview) self.fr_merge_actions.pack(side=TOP, fill=X) self.btn_execute_preview = Button(self.fr_merge_actions, text="Preview merge", command=self.on_preview_merge) self.btn_execute_preview.pack(side=LEFT) self.btn_execute_preview = Button(self.fr_merge_actions, text="Commit merge", command=self.on_commit_merge) self.btn_execute_preview.pack(side=LEFT) # Update self.merge_update = BooleanVar() self.e_merge_update = ttk.Checkbutton(self.fr_merge_actions, variable=self.merge_update) self.e_merge_update.pack(side=RIGHT) self.l_merge_update = ttk.Label(self.fr_merge_actions, text="Update: ") self.l_merge_update.pack(side=RIGHT) # Insert self.merge_insert = BooleanVar() self.e_merge_insert = ttk.Checkbutton(self.fr_merge_actions, variable=self.merge_insert) self.e_merge_insert.pack(side=RIGHT) self.l_merge_insert = ttk.Label(self.fr_merge_actions, text="Insert: ") self.l_merge_insert.pack(side=RIGHT) # Delete self.merge_delete = BooleanVar() self.e_merge_delete = ttk.Checkbutton(self.fr_merge_actions, variable=self.merge_delete) self.e_merge_delete.pack(side=RIGHT) self.l_merge_delete = ttk.Label(self.fr_merge_actions, text="Delete: ") self.l_merge_delete.pack(side=RIGHT) # Set post-merge SQL self.post_execute_sql = StringVar() self.btn_Post_Merge_SQL = ttk.Button(self.fr_merge_actions, text="Set post-merge SQL", command=self.on_post_merge_sql) self.btn_Post_Merge_SQL.pack(side=RIGHT, padx=30) # Preview self.gr_preview = ttk.Treeview(self.fr_Preview, columns=('size', 'modified')) self.gr_preview.pack(side=TOP, fill=BOTH, expand=1) self.gr_preview.bind("<<TreeviewSelect>>", self.on_preview_selected) self.preview_detail = StringVar() self.e_previev_detail = ttk.Entry(self.fr_Preview, textvariable=self.preview_detail) self.e_previev_detail.pack(side=BOTTOM, fill=X, expand=0) self.fr_bottom = BPMFrame(self.interior) self.fr_bottom.pack(side=BOTTOM, fill=X) self.fr_Status_Bar = Status_Bar(self.fr_bottom) self.fr_Status_Bar.pack(fill=X) print("done.") # ######################################################################### # This section contains functions handling the entire merge(load/save/GUI) # ######################################################################### def _merge_to_gui(self): """ Populate the GUI from the merge class. """ if self.fr_src_dataset is not None: self.fr_src_dataset.destroy() _src_type = self.dataset_instance_to_dataset_type(self.merge.source) self.sel_src_dataset_type.set_but_do_not_propagate(_src_type) self.fr_src_dataset = self.dataset_frame_factory(_dataset=self.merge.source, _is_destination=False) self.fr_src_dataset.grid(column=0, row=1) if self.fr_dest_dataset is not None: self.fr_dest_dataset.destroy() _dest_type = self.dataset_instance_to_dataset_type(self.merge.destination) self.sel_dest_dataset_type.set_but_do_not_propagate(_dest_type) self.fr_dest_dataset = self.dataset_frame_factory(_dataset=self.merge.destination, _is_destination=False) self.fr_dest_dataset.grid(column=1, row=1) self.mappings_to_gui() self.merge_insert.set(bool_to_binary_int(self.merge.insert)) self.merge_delete.set(bool_to_binary_int(self.merge.delete)) self.merge_update.set(bool_to_binary_int(self.merge.update)) if self.merge.post_execute_sql is None: self.post_execute_sql.set("") else: self.post_execute_sql.set(self.merge.post_execute_sql) # Hereafter, update column list when they change self.fr_src_dataset.on_columns_change = self.on_dataset_columns_change self.fr_dest_dataset.on_columns_change = self.on_dataset_columns_change def _gui_to_merge(self): """Copy the data from the GUI to the merge object""" self.fr_src_dataset.write_to_dataset() self.merge.source = self.fr_src_dataset.dataset self.fr_dest_dataset.write_to_dataset() self.merge.destination = self.fr_dest_dataset.dataset self.gui_to_mappings() self.merge.insert = binary_int_to_bool(self.merge_insert.get()) self.merge.delete = binary_int_to_bool(self.merge_delete.get()) self.merge.update = binary_int_to_bool(self.merge_update.get()) self.merge.post_execute_sql = self.post_execute_sql.get() def load_json(self, _filename): """Load an JSON into the merge object, and populate the GUI""" with open(_filename, "r") as _f: _json = json.load(_f) self.filename = _filename self.notify_task('Loading transformation..', 0) self.merge = Merge(_json=_json, _base_path=os.path.dirname(_filename)) try: self.merge._load_datasets() except Exception as e: self.notify_messagebox("Error loading data", str(e)) # Supress the following errors. There is no real errors that matters. self.suppress_errors = True self._merge_to_gui() self.suppress_errors = None self.notify_task('Loading transformation..done', 100) self.resize() def on_save_json(self, *args): """Triggered when save-button is clicked. Displays a save dialog, fetches GUI data into merge, and saves as JSON into the selected file.""" self.notify_task('Saving..', 0) _filename = filedialog.asksaveasfilename(initialfile= self.filename, defaultextension=".json", filetypes=[('JSON files', '.json'), ('all files', '.*')], title="Choose location") if _filename: self._gui_to_merge() self.notify_task('Saving(Generating JS)..', 0) _json = self.merge.as_json() self.notify_task('Saving(Writing file)..', 50) with open (_filename, "w") as _f: json.dump(_json, fp=_f, sort_keys=True, indent=4) self.notify_task('Saving..done.', 100) else: self.notify_task('Saving cancelled.', 0) def on_load_json(self, *args): """Triggered when load-button is clicked. Displays a load dialog, clears the GUI, populates the merge and uppdates the GUI""" _filename = filedialog.askopenfilename(defaultextension=".json", filetypes=[('JSON files', '.json'), ('all files', '.*')], title="Choose file") if _filename: self.g_transformations.clear() self.g_mappings.clear() self.clear_preview() self.curr_mapping_frame = None self._row_index = 0 self.load_json(_filename) def check_prerequisites_for_reload(self): """Can a reload be made using the current settings? If not, display cause in status field""" if self.fr_src_dataset is None: self.notify_task("Cannot reload: Source dataset must be specified.", 0) return False elif self.fr_dest_dataset is None: self.notify_task("Cannot reload: Destination dataset must be specified.", 0) return False _tmp = self.fr_src_dataset.check_reload() if _tmp: self.notify_task("Cannot reload source: " + _tmp, 0) return False _tmp = self.fr_dest_dataset.check_reload() if _tmp: self.notify_task("Cannot reload destination: " + _tmp, 0) return False else: return True def update_data(self, _refresh=None): """ Reload all data into the GUI :param _refresh: Force reload of datasets :return: """ if self.check_prerequisites_for_reload() is False: return self.notify_task("", 0) if len(self.merge.source.data_table) == 0 or _refresh: # Update settings self._gui_to_merge() # Update XPath references especially, since it addresses an XML structure, not a dataset. if isinstance(self.merge.source, XpathDataset): self.merge.source.field_xpaths = [] self.merge.source.field_names = [] for _curr_mapping_idx in range(0, len(self.g_mappings.items)): self.merge.source.field_xpaths.append( self.g_mappings.items[_curr_mapping_idx].fr_item.src_reference.get()) self.merge.source.field_names.append( self.g_mappings.items[_curr_mapping_idx].fr_item.src_reference.get()) self.merge.source.load() # Reset identity values self.reset_substitions_identity() # Is there any data? if len(self.merge.source.data_table) > 0: # Try to retain the approximate position in the table. if self._row_index < 0: self._row_index = 0 elif self._row_index > len(self.merge.source.data_table) - 1: self._row_index = len(self.merge.source.data_table) - 1 # Loop through mappings, update data and perform transformations # TODO: This certainly doesn't seem to belong here, should be extracted for _curr_mapping_idx in range(0, len(self.g_mappings.items)): _curr_frame = self.g_mappings.items[_curr_mapping_idx].fr_item _curr_frame.hide_error() _src_ref = _curr_frame.src_reference.get() try: if isinstance(self.merge.source, XpathDataset): _col_idx = self.merge.source.field_xpaths.index(_src_ref) else: _col_idx = self.merge.source.field_names.index(_src_ref) except ValueError: _col_idx = -1 if _col_idx > -1: _curr_frame.curr_raw_data = self.merge.source.data_table[self._row_index][_col_idx] try: perform_transformations(_input=_curr_frame.curr_raw_data, _transformations=_curr_frame.mapping.transformations) except Exception as e: self.notify_task( 'Error in one of the transformations, mapping: ' + _src_ref + " error: " + str(e), 0) _curr_frame.curr_data.set(str(_curr_frame.curr_raw_data)) else: _curr_frame.show_error(_msg="No mapping") _curr_frame.curr_data.set("") try: _curr_frame.curr_raw_data = perform_transformations(_input=None, _transformations= _curr_frame.mapping.transformations) except Exception as e: self.notify_task( 'Error in one of the transformations, mapping: ' + _curr_frame.dest_reference.get() + " error: " + str(e), 0) _curr_frame.curr_data.set(str(_curr_frame.curr_raw_data)) self.g_mappings.items[_curr_mapping_idx].fr_item.reload_references() # ######################################################### # The following events deals with navigating the active dataset ########################################################## def on_prev(self): """Triggered when the "<"-button is pressed.""" self._row_index -= 1 self.update_data() def on_next(self): """Triggered when the ">"-button is pressed.""" self._row_index += 1 self.update_data() def on_reload_data(self): """Triggered when the "Reload data"-button is pressed.""" self.update_data(_refresh=True) def on_first(self): """Triggered when the "<<"-button is pressed.""" self._row_index = 0 self.update_data() def on_last(self): """Triggered when the ">>!-button is pressed.""" if len(self.merge.source.data_table) == 0: self.merge.source.load() self._row_index = len(self.merge.source.data_table) - 1 self.update_data() def dataset_instance_to_dataset_type(self, _dataset): """ Identify an instance of a dataset and return a string description. Used in the dataset type selector. :param _dataset: The dataset to identify """ if isinstance(_dataset, RDBMSDataset): return "RDBMS" elif isinstance(_dataset, XpathDataset): return "XPATH" elif isinstance(_dataset, FlatfileDataset): return "FLATFILE" elif isinstance(_dataset, SpreadsheetDataset): return "SPREADSHEET" else: raise Exception("Internal error, unsupported dataset instance type: " + str(_dataset)) def dataset_frame_factory(self, _dataset=None, _dataset_type=None, _is_destination=False): """ This is a factory function for creating matching frames(visual property editors) for the dataset classes. :param _dataset: The dataset, if existing. :param _dataset_type: The dataset type string representation ("RDBMS", and so on) """ if _dataset: _dataset_type = self.dataset_instance_to_dataset_type(_dataset) if _dataset_type == "RDBMS": _tmp = FrameRDBMSDataset(self.fr_datasets, _dataset=_dataset, _relief=SUNKEN, _is_destination=_is_destination) _tmp.subnet_ip = self.ip_address elif _dataset_type == "FLATFILE": _tmp = FrameFlatfileDataset(self.fr_datasets, _dataset=_dataset, _relief=SUNKEN, _is_destination=_is_destination) elif _dataset_type == "XPATH": _tmp = FrameXPathDataset(self.fr_datasets, _dataset=_dataset, _relief=SUNKEN, _is_destination=_is_destination) elif _dataset_type == "SPREADSHEET": _tmp = FrameSpreadsheetDataset(self.fr_datasets, _dataset=_dataset, _relief=SUNKEN, _is_destination=_is_destination) else: raise Exception("Internal error, unsupported dataset type: " + str(_dataset_type)) if self.filename is not None: _tmp.base_path = os.path.dirname(self.filename) return _tmp def on_src_dataset_type_change(self, _current_value): """ Triggered when a user selects a different dataset type for the source dataset :param _current_value: A string describing what dataset type has been selected. """ if self.fr_src_dataset is not None: self.fr_src_dataset.destroy() self.fr_src_dataset = self.dataset_frame_factory(_dataset_type=_current_value.upper(), _is_destination=False) self.merge.source = self.fr_src_dataset.dataset self.fr_src_dataset.grid(column=0, row=1) def on_dest_dataset_type_change(self, _current_value): """ Triggered when a user selects a different dataset type for the destination dataset :param _current_value: A string describing what dataset type has been selected. """ if self.fr_dest_dataset is not None: self.fr_dest_dataset.destroy() self.fr_dest_dataset = self.dataset_frame_factory(_dataset_type=_current_value.upper(), _is_destination=True) self.merge.destination = self.fr_dest_dataset.dataset self.fr_dest_dataset.grid(column=1, row=1) def get_source_references(self, _force=None): """ Returns the possible field references from the source dataset :param _force: If True, forces a reload of the underlying dataset. """ if self.fr_src_dataset is not None: try: return self.fr_src_dataset.get_possible_references(_force) except Exception as e: self.notify_messagebox(_title="Failed refreshing source references", _message="Error: " + str(e), _kind="warning") return [] def get_destination_references(self, _force=None): """ Returns the possible field references from the destination dataset :param _force: If True, forces a reload of the underlying dataset. """ if self.fr_dest_dataset is not None: try: return self.fr_dest_dataset.get_possible_references(_force) except Exception as e: self.notify_messagebox(_title="Failed refreshing destination references", _message="Error: " + str(e), _kind="warning") return [] ########################################################## # This section contains functions handling field mappings ########################################################## def mappings_to_gui(self): """Populates the GUI from the mappings list of the merge object""" self.g_mappings.clear() for _curr_mapping in self.merge.mappings: _new_item = self.g_mappings.append_item() _new_item.make_item(_class=FrameMapping, _mapping=_curr_mapping, _on_get_source_references=self.get_source_references, _on_get_destination_references=self.get_destination_references) def gui_to_mappings(self): """Gathers data from GUI into the mappings list of the merge object""" self.gui_to_transformations() for _curr_mapping in self.g_mappings.items: _curr_mapping.fr_item.gui_to_mapping() self.merge._mappings_to_fields(self.merge.source, _use_dest=False) self.merge._mappings_to_fields(self.merge.destination, _use_dest=True) def mappings_do_on_delete(self, _g_mappings, _item_frame): """Triggered if the "del"-button has been clicked""" self.merge.mappings.remove(_item_frame.fr_item.mapping) def mappings_do_on_move_up(self, _g_mappings, _item_frame): """Triggered if the up arrow-button has been clicked""" _curr_idx = self.merge.mappings.index(_item_frame.fr_item.mapping) self.merge.mappings.insert(_curr_idx - 1, self.merge.mappings.pop(_curr_idx)) def mappings_do_on_move_down(self, _g_mappings, _item_frame): """Triggered if the down arrow-button has been clicked""" _curr_idx = self.merge.mappings.index(_item_frame.fr_item.mapping) self.merge.mappings.insert(_curr_idx + 1, self.merge.mappings.pop(_curr_idx)) def on_append_mapping(self, *args): """Triggered if the "Append mapping"-button has been clicked.""" _new_mapping = Mapping() self.merge.mappings.append(_new_mapping) _new_item = self.g_mappings.append_item() _new_item.make_item(_class=FrameMapping, _mapping=_new_mapping, _on_get_source_references=self.get_source_references, _on_get_destination_references=self.get_destination_references) def mappings_do_on_detail(self, _g_mappings, _item_frame): self.notify_task("", 0) if self.curr_mapping_frame: self.gui_to_transformations() self.g_transformations.clear() for _curr_transformation in _item_frame.fr_item.mapping.transformations: _frame_class = self._transformation_frame_class_lookup(_curr_transformation) if _frame_class: _new_item = self.g_transformations.append_item() _new_item.make_item(_class=_frame_class, _transformation=_curr_transformation) _item_frame['background'] = "dark grey" try: if _item_frame.fr_item.curr_raw_data is not None: perform_transformations(_input=_item_frame.fr_item.curr_raw_data, _transformations=_item_frame.fr_item.mapping.transformations) except Exception as e: self.notify_task( 'Error in one of the transformations, mapping: ' + _item_frame.fr_item.mapping.src_reference + " error: " + str( e), 0) if self.curr_mapping_frame: try: self.curr_mapping_frame['background'] = self['background'] except Exception as e: raise Exception("Error setting background to: " + self['background'] + ":" + str(e)) self.curr_mapping_frame = _item_frame ########################################################## # This section contains functions handling transformations ########################################################## def gui_to_transformations(self): """Gathers data from GUI into the transformation objects""" for _curr_transformation in self.g_transformations.items: _curr_transformation.fr_item.gui_to_transformation() def _transformation_frame_class_lookup(self, _transformation=None, _type=None): if _type is None: _type, _desc = transformation_to_type(_transformation) if _type == "Cast": return FrameTransformationCast if _type == "Trim": return FrameTransformationTrim if _type == "If empty": return FrameTransformationIfEmpty if _type == "Replace": return FrameTransformationReplace if _type == "Replace regex": return FrameTransformationReplaceRegex else: return None #raise Exception("Internal error, unsupported transformation type: " + str(_transformation_type)) def transformations_do_on_delete(self, _g_transformations, _item_frame): self.curr_mapping_frame.fr_item.mapping.transformations.remove(_item_frame.fr_item.transformation) def transformations_do_on_move_up(self, _g_transformations, _item_frame): _curr_transformations = self.curr_mapping_frame.fr_item.mapping.transformations _curr_idx = _curr_transformations.index(_item_frame.fr_item.transformation) _curr_transformations.insert(_curr_idx - 1, _curr_transformations.pop( _curr_idx)) def transformations_do_on_move_down(self, _g_transformations, _item_frame): _curr_transformations = self.curr_mapping_frame.fr_item.mapping.transformations _curr_idx = _curr_transformations.index(_item_frame.fr_item.transformation) _curr_transformations.insert(_curr_idx + 1, _curr_transformations.pop( _curr_idx)) def on_append_transformation(self, *args): if self.curr_mapping_frame is not None: _new_transformation = type_to_transformation(self.sel_transformation_append_type.get())( _substitution=self.curr_mapping_frame.fr_item.mapping.substitution) self.curr_mapping_frame.fr_item.mapping.transformations.append(_new_transformation) _frame_class = self._transformation_frame_class_lookup(_new_transformation) if _frame_class: _new_item = self.g_transformations.append_item() _new_item.make_item(_class=_frame_class, _transformation=_new_transformation) def clear_transformation_events(self): for _curr_mapping in self.merge.mappings: for _curr_transformation in _curr_mapping.transformations: _curr_transformation.on_done = None ############################################################ # This section contains functions handling the merge preview ############################################################ def clear_preview(self): for _curr_item in self.gr_preview.get_children(): self.gr_preview.delete(_curr_item) def reset_substitions_identity(self): """Reset substitions""" for _curr_mapping in self.merge.mappings: _curr_mapping.substitution.set_identity(0) def on_preview_merge(self, *args): self.do_merge(_commit=False) def on_commit_merge(self, *args): if askokcancel(title="Warning: committing merge", message="This will commit actual changes to the destination, " "do you want to proceed?") is True: self.do_merge(_commit=True) def do_merge(self, _commit=False): self._gui_to_merge() self.update_data(_refresh=True) self.merge.destination_log_level = DATASET_LOGLEVEL_DETAIL # Clear GUI events self.clear_transformation_events() self.merge.clear_log() try: _data_table, _log, _deletes, _inserts, _updates = self.merge.execute(_commit=_commit) except Exception as e: self.notify_messagebox("Error while merging", str(e)) return # Call columns src/dest field names if they differ if len(self.merge.key_fields) > 0: _key_field = self.merge.key_fields[0] else: _key_field = 0 self.clear_preview() self.gr_preview["columns"] = ["Change_Data"] self.gr_preview.column("Change_Data", width=500) self.gr_preview.heading("Change_Data", text="Change/Data") # Add a main for each action # Add deletes self.gr_preview.insert(parent="", index="end", iid="obpm_deletes", text="Deletes") if self.merge.delete: for _curr_row in _deletes: _curr_item_idx = self.gr_preview.insert(parent="obpm_deletes", index="end", iid="", text=_curr_row[2][_key_field]) _curr_value = ",".join([str(_item) for _item in _curr_row[2]]) self.gr_preview.item(_curr_item_idx, values=[_curr_value]) for _curr_column_idx in range(len(_curr_row[2])): _curr_change_item_idx = self.gr_preview.insert(parent=_curr_item_idx, index="end", iid="", text=str( self.merge.destination.field_names[_curr_column_idx])) self.gr_preview.item(_curr_change_item_idx, values=[str(_curr_row[2][_curr_column_idx])]) # Add inserts self.gr_preview.insert(parent="", index="end", iid="obpm_inserts", text="Inserts") if self.merge.insert: for _curr_row in _inserts: _curr_item_idx = self.gr_preview.insert(parent="obpm_inserts", index="end", iid="", text=_curr_row[2][_key_field]) _curr_value = ",".join([str(_item) for _item in _curr_row[2]]) self.gr_preview.item(_curr_item_idx, values=[_curr_value]) for _curr_column_idx in range(len(_curr_row[2])): _curr_change_item_idx = self.gr_preview.insert(parent=_curr_item_idx, index="end", iid="", text=str( self.merge.destination.field_names[_curr_column_idx])) self.gr_preview.item(_curr_change_item_idx, values=[str(_curr_row[2][_curr_column_idx])]) # Add updates self.gr_preview.insert(parent="", index="end", iid="obpm_updates", text="Updates") if self.merge.update: for _curr_row in _updates: _curr_item_idx = self.gr_preview.insert(parent="obpm_updates", index="end", iid="", text=_curr_row[2][_key_field]) _changes = [] for _curr_column_idx in range(len(_curr_row[2])): if _curr_row[2][_curr_column_idx] != _curr_row[3][_curr_column_idx]: _curr_change_item_idx = self.gr_preview.insert(parent=_curr_item_idx, index="end", iid="", text=str(self.merge.destination.field_names[ _curr_column_idx])) self.gr_preview.item(_curr_change_item_idx, values=[ str(_curr_row[3][_curr_column_idx]) + "=>" + str(_curr_row[2][_curr_column_idx])]) _changes.append(str(self.merge.destination.field_names[_curr_column_idx])) _curr_value = ",".join([str(_item) for _item in _changes]) self.gr_preview.item(_curr_item_idx, values=[_curr_value]) # Add log self.gr_preview.insert(parent="", index="end", iid="obpm_log", text="Log") if _log is not None: for _curr_row in _log: _log_fields = _curr_row.split(";") _curr_item_idx = self.gr_preview.insert(parent="obpm_log", index="end", iid="", text=_log_fields[0]) _curr_value = ",".join([unquote(str(_item)) for _item in _log_fields[1:]]) self.gr_preview.item(_curr_item_idx, values=[_curr_value]) # Add data table self.gr_preview.insert(parent="", index="end", iid="obpm_data_table", text="Result") if _data_table is not None: for _curr_row in _data_table: _curr_item_idx = self.gr_preview.insert(parent="obpm_data_table", index="end", iid="", text=_curr_row[_key_field]) _curr_value = ",".join([str(_item) for _item in _curr_row]) self.gr_preview.item(_curr_item_idx, values=[_curr_value]) for _curr_column_idx in range(len(_curr_row)): _curr_change_item_idx = self.gr_preview.insert(parent=_curr_item_idx, index="end", iid="", text=str( self.merge.destination.field_names[_curr_column_idx])) self.gr_preview.item(_curr_change_item_idx, values=[str(_curr_row[_curr_column_idx])]) if _commit == True: _simulation_expression = "Merge" else: _simulation_expression = "Simulated merge" if not (self.merge.insert or self.merge.delete or self.merge.update): self.notify_task( _simulation_expression + " done. (Expecting merge results? Neither insert, delete or update is selected)", 100) else: self.notify_task(_simulation_expression + " done.", 100) def on_preview_selected(self, *args): _selection = self.gr_preview.selection() if len(_selection) > 0: _item = self.gr_preview.item(_selection[0]) self.preview_detail.set(str(",".join([str(_item) for _item in _item["values"]])))