def parse_n_load_possible_widgets(myxml_file='', window=None, values={}): ''' возвращает найденые object_names все виджетов ''' if os.path.exists(myxml_file) and os.path.isfile(myxml_file): # get xml with open(myxml_file, 'r', encoding='utf-8') as ff: xml_code = ff.read() # filter object names widgets_regexpattern = make_regex( r"^[ \s]{1,}<(widget)\s?.*?\s?name=\"(.+)\"\/?>", MULTILINE) layouts_regexpattern = make_regex( r"^[ \s]{1,}<(layout)\s?.*?\s?name=\"(.+)\"\/?>", MULTILINE) widgets = [ i.group(2) for i in finditer(widgets_regexpattern, xml_code) ] layouts = [ i.group(2) for i in finditer(layouts_regexpattern, xml_code) ] widgets.sort() layouts.sort() # ##################### # обработка id виджетов # ##################### for i in widgets: if '"' in i: i = i[:i.index('"')] for i in layouts: if '"' in i: i = i[:i.index('"')] # ###### # insert # ###### combo_items = [ '# pick LAYOUTS widgets #', *layouts, '# pick WIDGETS widgets #', *widgets ] window['objs'].update(values=combo_items) update_clear_btn(window, values) el = combo_items[1] if ' ' not in el: window['objname'].update(el) update_clear_btn(window, values, real_value=el) return combo_items else: window['objs'](values=[]) window['objname']('') return []
def do_mice_events(ui, boilerplate): # find regex pattern from all buttons regex_pattern = make_regex( r'(RButton|ReadButton|B)\([\'\"][\w\ \_\d]*[\'\"],?\s?((key)\s*=\s*[\'\"]([\w\ \_\d]+?)[\'\"])') # find all keys in you ui keys = [i.group(4) for i in finditer(regex_pattern, ui)] return boilerplate.replace('# ~TARGET', do_callbacks(keys))
def clear_empty_top_widget(ui): ''' clear ui to easyily for coping functionality (ctrl+c) ''' ''' # case1 sg.Frame('', key='gridLayout', layout = [ [sg.RButton('PushButton', key='pushButton'), sg.RButton('PushButton', key='pushButton_2')] ]) ''' first_line = ui.split('\n')[0] regex_matched = make_regex( r"^sg.Frame\('',\s?key='.*',\slayout\s=\s\[").match(first_line) if regex_matched and ui[-2:] == '])': new_ui = '[\n' + '\n'.join(ui.split('\n')[1:]).strip() return new_ui[:-1] return ui
def run_gui(): def clear_empty_top_widget(ui): ''' clear ui to easyily for coping functionality (ctrl+c) ''' ''' # case1 sg.Frame('', key='gridLayout', layout = [ [sg.RButton('PushButton', key='pushButton'), sg.RButton('PushButton', key='pushButton_2')] ]) ''' first_line = ui.split('\n')[0] regex_matched = make_regex( r"^sg.Frame\('',\s?key='.*',\slayout\s=\s\[").match(first_line) if regex_matched and ui[-2:] == '])': new_ui = '[\n' + '\n'.join(ui.split('\n')[1:]).strip() return new_ui[:-1] return ui def update_clear_btn(my_window, my_values, real_value=''): objname = my_values['objname'] if real_value == '' else real_value all_object_names_in_combo = my_window.Element('objs').Values if my_values[ 'xmlfile'] and objname and objname in all_object_names_in_combo: my_window.Element('compile_btn').Update(disabled=False) my_window.Element('compilepp_btn').Update(disabled=False) else: my_window.Element('compile_btn').Update(disabled=True) my_window.Element('compilepp_btn').Update(disabled=True) # _ # (_) # __ _ _ _ _ # / _` | | | | | # | (_| | |_| | | # \__, |\__,_|_| # __/ | # |___/ ralign = {'size': (16, 3), "justification": 'r'} input_frame = [[ sg.T('\nxml file', **ralign), sg.In(key='xmlfile', change_submits=True), sg.FileBrowse(target='xmlfile'), sg.T('possible\nobject names', justification='r'), sg.InputCombo(values=[''], key='objs', size=(40, 1), change_submits=True) ], [ sg.T('\nTarget object name', **ralign), sg.In(key='objname', change_submits=True), sg.B('compile', key='compile_btn', disabled=True), sg.B('compile++', key='compilepp_btn', disabled=True), sg.Radio('all keys', 1, True, key='r2_keys'), sg.Radio('mouse clicks', 1, key='r2_mouse_clicks') ]] tab1_layout = [[sg.Frame('Input data', input_frame)], [ sg.B('Clear'), sg.CB('forget about bad widgets', True, key='no_bad_widgets'), sg.CB('empty top widget', True, key='empty_top_widget') ], [sg.Multiline(key='psg_ui_output', size=(120, 14))]] tab2_layout = [[sg.Image(filename='', key='psg_image')]] layout = [[ sg.TabGroup([[ sg.Tab('transpiler', tab1_layout), sg.Tab('hot transpiler', tab2_layout, disabled=True) ]]) ]] window = sg.Window('Transpiler', layout=layout, auto_size_buttons=False, default_button_element_size=(10, 1)) while True: # Event Loop event, values = window.Read() # window.Element('psg_image').Update(filename='imgs/' + random.choice('1.png 2.png 3.png 4.png'.split(' '))) if event in (None, 'Exit'): break elif event == 'xmlfile': myxml_file = values['xmlfile'] if os.path.exists(myxml_file): # get xml with open(myxml_file, 'r', encoding='utf-8') as ff: xml_code = ff.read() # filter object names widgets_regexpattern = make_regex( r"^[ \s]{1,}<(widget)\s?.*?\s?name=\"(.+)\"\/?>", MULTILINE) layouts_regexpattern = make_regex( r"^[ \s]{1,}<(layout)\s?.*?\s?name=\"(.+)\"\/?>", MULTILINE) widgets = [ i.group(2) for i in finditer(widgets_regexpattern, xml_code) ] layouts = [ i.group(2) for i in finditer(layouts_regexpattern, xml_code) ] combo_items = [ '# LAYOUTS widgets #', *layouts, '# WIDGETS widgets #', *widgets ] # set it window.Element('objs').Update(values=combo_items) update_clear_btn(window, values) el = combo_items[1] if ' ' not in el: window.Element('objname').Update(el) update_clear_btn(window, values, real_value=el) elif event == 'objs': # add only REAL object names -> those, who not contain ' ' if ' ' not in values['objs']: window.Element('objname').Update(values['objs']) update_clear_btn(window, values, real_value=values['objs']) elif event == 'objname': update_clear_btn(window, values) elif event == 'Clear': window.Element('psg_ui_output').Update('') elif event == 'compile_btn': ui = just_compile(values) if values['empty_top_widget']: ui = clear_empty_top_widget(ui) window.Element('psg_ui_output').Update(ui) elif event == 'compilepp_btn': ui = just_compile(values) # case for 'speed up' # psg_ui_output = values['psg_ui_output'] # ui = ... psg_ui_output ... ui = just_compile(values) if values['empty_top_widget']: ui = clear_empty_top_widget(ui) psg_ui = build_boilerplate(layout=ui, mouse_clicks=values['r2_mouse_clicks'], keys=values['r2_keys']) window.Element('psg_ui_output').Update(psg_ui) elif event == 'Try in PySimpleGUI': pass # try: # ui = values['psg_ui_output'].strip() # if ui[:18] == "sg.Frame('', key='" and ui[-2:] == "])": # ui = ui[ui.index('['):-1] # elif ui[0] == "[" and ui[-1] == "]": # pass # window2 = sg.Window('test', myui) # window2.Read() # window2.Close() # except Exception as e: # mbox(str(e)) window.Close()
def do_keys_events(ui, boilerplate): # find regex pattern from all elements regex_pattern = make_regex(r'(key)\s*=\s*[\'\"]([\w\d]+?)[\'\"]') # find all keys in you ui keys = [i.group(2) for i in finditer(regex_pattern, ui)] return boilerplate.replace('# ~TARGET', do_callbacks(keys))
def run_gui(): settings_path = os.path.join(cd, 'setting.json') def clear_empty_top_widget(ui): ''' clear ui to easyily for coping functionality (ctrl+c) ''' ''' # case1 sg.Frame('', key='gridLayout', layout = [ [sg.RButton('PushButton', key='pushButton'), sg.RButton('PushButton', key='pushButton_2')] ]) ''' first_line = ui.split('\n')[0] regex_matched = make_regex( r"^sg.Frame\('',\s?key='.*',\slayout\s=\s\[").match(first_line) if regex_matched and ui[-2:] == '])': new_ui = '[\n' + '\n'.join(ui.split('\n')[1:]).strip() return new_ui[:-1] return ui def update_clear_btn(my_window, my_values, real_value=''): objname = my_values['objname'] if real_value == '' else real_value all_object_names_in_combo = my_window['objs'].Values if my_values['xmlfile'] and objname and objname in all_object_names_in_combo: my_window['convert_btn'].update(disabled=False) my_window['convert_all_events'].update(disabled=False) my_window['convert_btns_events'].update(disabled=False) else: my_window['convert_btn'].update(disabled=True) my_window['convert_all_events'].update(disabled=True) my_window['convert_btns_events'].update(disabled=True) def update_app_settings(): with open(settings_path, 'w', encoding='utf-8') as f: json.dump(_settings, f, ensure_ascii=False, indent=2) if os.path.exists(settings_path): try: with open(settings_path, 'r', encoding='utf-8') as f: _settings = json.load(f) except Exception as e: _settings = { '-memento-file-cb-': False, 'xmlfile': '' } update_app_settings() else: _settings = { '-memento-file-cb-': False, 'xmlfile': '' } update_app_settings() ############### ### GUI ### ############### ralign = {'size': (16, 1), "justification": 'r'} main_layout = [ [sg.T('xml file', **ralign), sg.I(key='xmlfile', size=(35, 2), change_submits=True), sg.FileBrowse(target='xmlfile')], [sg.T('target object name', **ralign), sg.I(key='objname', size=(35, 2), change_submits=True)], [sg.T('all object names', **ralign), sg.Drop(values=[''], key='objs', size=(34, 1), change_submits=True) ], [ sg.T('', **ralign), sg.B('convert', key='convert_btn', disabled=True), sg.B('convert++\nall events', size=(-1, 2), key='convert_all_events', disabled=True), sg.B('convert++\nbtns events', size=(-1, 2), key='convert_btns_events', disabled=True) ], [ sg.T('options:', **ralign), sg.CB('try convert unknows widgets', True, key='no_bad_widgets') ], ] settings_layout = [ [sg.CB('Remember path to previous file', False, change_submits=True, key='-memento-file-cb-')], [sg.T('Indent size', key='indent_size '), sg.I('1', size=(5, 1), key='indent_size')], [sg.T('Indent char', key='indent_char '), sg.I(' ', size=(5, 1), key='indent_char')], ] layout = [ [ sg.TabGroup([[ sg.Tab('transpiler', main_layout), sg.Tab('settings', settings_layout) ]]), sg.Frame('Output data', layout=[ [sg.B('Clear output', key='clear_btn'), sg.B('Execute output (used after convert++)', size=(35, 1), disabled=True, key='Try')], [sg.ML(key='psg_ui_output', size=(60, 15))] ], key='message_board', metadata='Output data')], ] window = sg.Window('Transpiler', layout, auto_size_buttons=False, default_button_element_size=(10, 1), finalize=True, location=(100, 100)) # setup if _settings['-memento-file-cb-']: window['-memento-file-cb-'].update(True) window['xmlfile'].update(_settings['xmlfile']) timers = [] def send_board_message(text='*** Done ***', window=None): curr_title = window['message_board'].metadata new_title = '{} | {} '.format(curr_title, text) window['message_board'].TKFrame.config(text=new_title) # counter end -> execute this: def clear_frame(): new_board_message = window['message_board'].metadata window['message_board'].TKFrame.config(text=new_board_message) return {'count': 1, 'finished' : clear_frame} # loop prev_values = None first_time_running = True while True: # первый запуск -> подгружка имен из xmlfile, если он есть if first_time_running: event, values = window.read(timeout=0) event = 'xmlfile' first_time_running = False else: event, values = window.read(timeout=500) if event in (None, 'Exit'): break # сдежка за таймерами и их работами for a_timer in timers: if a_timer['count'] > 0: a_timer['count'] -= 1 elif a_timer['count'] == 0: a_timer['finished']() timers.remove(a_timer) ################################ # _ _ # # | | (_) # # | | ___ __ _ _ ___ # # | |/ _ \ / _` | |/ __| # # | | (_) | (_| | | (__ # # |_|\___/ \__, |_|\___| # # __/ | # # |___/ # ################################ indend_size_n_char = int(values['indent_size']), values['indent_char'] prev_values = values if event == '-memento-file-cb-': _settings['-memento-file-cb-'] = values['-memento-file-cb-'] _settings['xmlfile'] = '' if values['-memento-file-cb-'] else values['xmlfile'] update_app_settings() elif event == 'xmlfile': myxml_file = values['xmlfile'].strip() # remember this file if _settings['-memento-file-cb-']: _settings['xmlfile'] = myxml_file update_app_settings() if os.path.exists(myxml_file) and os.path.isfile(myxml_file): # get xml with open(myxml_file, 'r', encoding='utf-8') as ff: xml_code = ff.read() # filter object names widgets_regexpattern = make_regex( r"^[ \s]{1,}<(widget)\s?.*?\s?name=\"(.+)\"\/?>", MULTILINE) layouts_regexpattern = make_regex( r"^[ \s]{1,}<(layout)\s?.*?\s?name=\"(.+)\"\/?>", MULTILINE) widgets = [i.group(2) for i in finditer( widgets_regexpattern, xml_code)] layouts = [i.group(2) for i in finditer( layouts_regexpattern, xml_code)] widgets.sort() layouts.sort() combo_items = ['# pick LAYOUTS widgets #', *layouts, '# pick WIDGETS widgets #', *widgets] # set it window['objs'].update(values=combo_items) update_clear_btn(window, values) el = combo_items[1] if ' ' not in el: window['objname'].update(el) update_clear_btn(window, values, real_value=el) else: window['objs'].update(values=[]) window['objname'].update('') elif event == 'objs': # add only REAL object names -> those, who not contain ' ' if ' ' not in values['objs']: window['objname'].update(values['objs']) update_clear_btn(window, values, real_value=values['objs']) elif event == 'objname': update_clear_btn(window, values) elif event == 'clear_btn': window['psg_ui_output'].update('') elif event == 'convert_btn': ui = just_compile(values, *indend_size_n_char) window['psg_ui_output'].update(ui) if ui.startswith('Error:'): # fail timers.append(send_board_message(text='*** Fail ***', window=window)) else: # success timers.append(send_board_message(text='*** Done ***', window=window)) elif event == 'convert_all_events': ui = just_compile(values, *indend_size_n_char) psg_ui = build_boilerplate(layout=ui, btns_event=False, all_events=True) if ui.startswith('Error:'): # fail window['psg_ui_output'].update(ui) timers.append(send_board_message(text='*** Fail ***', window=window)) else: # success window['psg_ui_output'].update(psg_ui) timers.append(send_board_message(text='*** Done ***', window=window)) elif event == 'convert_btns_events': ui = just_compile(values, *indend_size_n_char) psg_ui = build_boilerplate(layout=ui, btns_event=True, all_events=False) if ui.startswith('Error:'): # fail window['psg_ui_output'].update(ui) timers.append(send_board_message(text='*** Fail ***', window=window)) else: # success window['psg_ui_output'].update(psg_ui) timers.append(send_board_message(text='*** Done ***', window=window)) elif event == 'Try': try: psg_ui = values['psg_ui_output'].strip() psg_ui_lines = psg_ui.split('\n') ''' case 1: import PySimpleGUI as sg ... case 2: sg.Frame('', layout = [ [...], [...], [...], ]) case 3: [ [...], [...], [...], ] ''' if psg_ui.startswith('import PySimpleGUI as sg'): exec(psg_ui) if psg_ui_lines[0].startswith("""sg.Frame('""") and psg_ui_lines[0].endswith("""', layout = ["""): window2 = sg.Window('test', eval(psg_ui)) window2.read() window2.close() if psg_ui_lines[0].startswith("""[""") and psg_ui_lines[-1].endswith("""]"""): possible_ui = eval(psg_ui) possible_ui if type(possible_ui) is list and type(possible_ui[0]) is not list: raise Exception(f"bad ui given. It's not a list of LISTS.") window2 = sg.Window('test', possible_ui) window2.read() window2.close() except Exception as e: sg.popup(str(e)) window.close()