def janelareceita( NOME, RECEITA_IMAGEM, RECEITA_INGREDIENTES, RECEITA_CATEGORIAS, RECEITA_MODOPREPARO ): window.Disable() LAYOUT2 = [ [sg.Stretch(), sg.Text(NOME, font=("SegoeUI bold", 24)), sg.Stretch()], [sg.HorizontalSeparator()], [ sg.Column( [ [sg.Stretch(), sg.Image(data=RECEITA_IMAGEM), sg.Stretch()], [sg.Text("Ingredientes:")], [sg.Listbox(RECEITA_INGREDIENTES)], [sg.Text("Categorias:")], [sg.Listbox(RECEITA_CATEGORIAS)], ] ), sg.VerticalSeparator(), sg.Column( [[sg.Text("MODO DE PREPARO:")], [sg.Multiline(RECEITA_MODOPREPARO)]] ), ], ] window2 = sg.Window( "Livro de Receitas", layout=LAYOUT2, size=(1200, 600), keep_on_top=True, ) while 1: event2, values2 = window2.read() if event2 == sg.WINDOW_CLOSED: break window2.close() window.Enable()
def main(): # Define theme for the GUI sg.theme('Light Grey 1') # Create a list of all of the accounts in the userdata file. account_names = userdata.get_names() # Define the icon in base64 format - this is the FontAwesome arrows-alt icon. # Create a column for the account list and the post GUI. acct_col = [[sg.Text('Select accounts to post to:')], [sg.Listbox(values=account_names, size=(20, 12))]] post_col = [[sg.Text('Subject/Content Warning (leave blank for none)')], [sg.Input(size=(50, 1))], [sg.Text("What's on your mind?")], [sg.Multiline(size=(50, 15))], [ sg.Text(justification='right', key='-CHARS-', margins=(10, 10, 10, 10)), sg.Button("Post!", size=(10, 1)) ]] # Combine both columns in one layout, and define the layout in the main window. layout = [[sg.Column(acct_col), sg.Column(post_col)]] window = sg.Window('Cross - A Mastodon/Hubzilla cross-poster', layout, icon=common.fa_arrows) # Start an loop that watches for window events and post length. while True: # This will update the post length counter every 20 milliseconds if I'm understanding correctly. # And, of course, will also do the event listening and monitor the values of the different items. event, values = window.read(timeout=20) if event in (None, 'Post!'): if event == 'Post!': # If we get here, the user pressed the post button. # Let's do a few sanity checks - first, let's make sure an account was selected to post to. if not values[0]: # If we're here, no accounts were selected. sg.popup_ok( "You didn't select any accounts!\n" "Try selecting an account before posting.\n", title="Error making post", icon=common.fa_arrows) # Next, let's make sure they actually wrote a post. elif values[2] == "": # They didn't actually write a post. Error out and let them know why. sg.popup_ok( "You didn't actually write a post, silly!\n" "Try writing one first.", title="Error making post", icon=common.fa_arrows) # We /should/ be good to continue at this point. else: userdata.post_sel_accts(values[0], values[1], values[2]) # And once we get here, we're done! Print a thank-you message in the console, break, and exit. print() print("Done! Thank you for using Cross.") # We've either finished posting or the user closed the window. Either way, let's break. break # If we get here, we're not breaking or posting, so update the post length counter with # the combined length of the subject/content warning and the post. window['-CHARS-'].update(str(len(values[1]) + len(values[2]))) window.close()
def show_clip_list_window(self, clips): """ Show all received clips in a Windows with a Listview and allow user select and copy an entry """ # TODO: Show Only preview of Clip to reduce length layout = [ [ sg.Listbox( values=clips, size=(60, 6), select_mode="LISTBOX_SELECT_MODE_SINGLE", key="sel_clip", ) ], [sg.Button("Copy to clipboard", size=(20, 1)), sg.Cancel(size=(20, 1))], ] window = sg.Window( title=f"{Config.APP_NAME} - Your Clips", layout=layout, size=(600, 300), icon=Config.ICON_B64, ) event, values = window.read() if event in (sg.WIN_CLOSED, "Cancel"): log.debug("List Clips selection canceled") pass elif event == "Copy to clipboard": Api.paste(values.get("sel_clip")[0]) window.close()
def autocomplete_popup_show(text_list): autocomplete_popup_layout = [[ sg.Listbox(values=text_list, size=(100, 20 * len(text_list)) if QT else (15, len(text_list)), change_submits=True, bind_return_key=True, auto_size_text=True, key='_FLOATING_LISTBOX_', enable_events=True) ]] autocomplete_popup = sg.Window("Borderless Window", default_element_size=(12, 1), auto_size_text=False, auto_size_buttons=False, no_titlebar=True, grab_anywhere=True, return_keyboard_events=True, keep_on_top=True, background_color='black', location=(1320, 622), default_button_element_size=(12, 1)) window = autocomplete_popup.Layout(autocomplete_popup_layout).Finalize() return window
def SendTC(file_name, instrument_type, note): flights = [ 'FLOATS_51', 'FLOATS_52', 'FLOATS_53', 'RACHuTS_51', 'RACHuTS_52', 'RACHuTS_53', 'LPC_51', 'LPC_52', 'LPC_53' ] flight_layout = [[ sg.Listbox(values=flights, key='_param_', tooltip='Select balloon/instrument to send TC to', size=(20, 6), font=Font) ]] layout_config_TC = [ [sg.Frame('Select Instrument/Flight: ', flight_layout, font=Font)], #[sg.Frame('Input new value: ', value_layout, font = Font)], [ sg.Submit(font=Font, pad=(10, 10)), sg.Cancel(font=Font, pad=(10, 10)) ] ] param_window = sg.Window('Select Flight', layout_config_TC) event, values = param_window.Read() param_window.Close() instrument = values['_param_'][0] print(instrument) print(event) if event == 'Submit': curl_cmnd(instrument, file_name, note)
def build_basic_layout(self): return [[sg.Text('RGB area:', key='AREAS_TXT')], [ sg.Listbox(values=self.areas, size=(20, len(self.areas)), enable_events=True, key='AREAS', default_values=self.current_area) ], [sg.Text('Effect:', key='EFFECTS_TXT')], [ sg.Listbox(values=list(self.effects.keys()), key='EFFECTS', size=(20, len(self.areas)), enable_events=True, default_values=self.current_effect) ]]
async def main() -> None: queue = await get_queue(host) # type: Deque[Job] output = ["Currently Running Job:", str(queue.popleft()), "Other Jobs:"] # type: List[Union[str, Job]] output.extend(queue) for job in queue: print(str(job)) layout = [[sg.Text("Here are the jobs:")], [sg.Listbox(output)], [sg.CloseButton("Close")]] window = sg.Window(title="Cloud Convert Client", layout=layout) event, values = window.Read() pprint.pprint(event) pprint.pprint(values)
def __repr__(self): return f'{self.num} {self.psg_object}' @staticmethod def headers(): return 'num,psg_object'.split(',') items = [ ParsingError(dicta1, 45), ParsingError(dicta2, 42), ParsingError(dicta3, 12), ] window = sg.Window('Test', [ [sg.Listbox(items, key='qwe', enable_events=True)], [sg.B('q1'), sg.B('q2'), sg.B('q3')], ], return_keyboard_events=True) while True: event, values = window() if event in ('Exit', None): break print(event, values) if event == 'q1': gui = values['qwe'][0] print(gui.num) print(gui.psg_object[4])
'This is the default Text should you decide not to type anything', size=(220, 80)), sg.Multiline(default_text='A second multi-line', size=(220, 80)) ], [ sg.InputCombo(('Combobox 1', 'Combobox 2'), size=(150, 22)), sg.Stretch(), sg.Slider(range=(1, 100), orientation='h', size=(300, 22), default_value=85) ], [sg.InputOptionMenu(('Menu Option 1', 'Menu Option 2', 'Menu Option 3'))], [ sg.Listbox(values=('Listbox 1', 'Listbox 2', 'Listbox 3'), size=(200, 100), select_mode=sg.LISTBOX_SELECT_MODE_EXTENDED), sg.Stretch(), sg.Frame('Labelled Group', [[ sg.Slider(range=(1, 100), orientation='v', default_value=25, tick_interval=25), sg.Slider(range=(1, 100), orientation='v', default_value=75), sg.Slider(range=(1, 100), orientation='v', default_value=10), sg.Column(column1, background_color='lightblue') ]], background_color='black'), sg.Stretch() ], [sg.Text('_' * 50, justification='c')], [sg.Text('Choose A Folder')], [
[sg.Input(key="nome_val"), sg.Button("Pesquisar", size=(10, 1), key="pesq_nome")], [ sg.Text( "Pesquisa por ingredientes (separado por vírgula, deixe vazio para ver todas as receitas):" ) ], [ sg.Radio("Apenas", "rgroup", default=True, key="rad_apenas"), sg.Radio("Também", "rgroup", key="rad_tambem"), ], [ sg.Input(key="ingred_val"), sg.Button("Pesquisar", size=(10, 1), key="pesq_ingred"), ], [sg.Text("Resultados:")], [sg.Listbox([], enable_events=True, key="resultados")], ] ABA1_COL2 = [ [ sg.Text("Listar todos os ingredientes:"), sg.Button("Listar", size=(10, 1), key="con_lista_ingredientes"), sg.Text("Listar todas as categorias:"), sg.Button("Listar", size=(10, 1), key="con_lista_cat"), ], [sg.Listbox([], key="con_ingredientes_listbox", enable_events=True), sg.Listbox([], key="con_cat_listbox", enable_events=True)], ] ABA1_COLS = [[sg.Column(ABA1_COL1), sg.Column(ABA1_COL2)]] ABA1 = sg.Tab(title="Consultar uma receita", layout=ABA1_COLS) ABA2_COL1 = [ [sg.Text("Nome:"), sg.Input(key="in_nome")],
headings=["st", "gg"], auto_size_columns=True, num_rows=10, col0_width=100, key='tree_' + behavior_type, size=(400, 120), select_mode=TABLE_SELECT_MODE_EXTENDED, change_submits=True, show_expanded=False, enable_events=True) behavior_entry['tree'] = behavior_tree behavior_entry['tree_data'] = tree selected = sg.Listbox(values=[], key='selected_' + behavior_type, enable_events=True, disabled=True, size=(100, 70)) behavior_entry['select'] = selected add_frame = [ sg.Frame('Actions', [[sg.Text('Parents: '), selected], [ sg.Button('Add', size=BUTTON_SIZE, key='add_behavior_' + behavior_type), sg.Button('Remove', size=BUTTON_SIZE, key='remove_behavior_' + behavior_type) ]], size=(300, 50))
ref_dir_elem = [[ sg.Text('Choose a directory containing the REFERENCE images: ', font=("Helvetica", 18)) ], [ sg.InputText(basePath, key='_REF_DIR_', size=(50, 0.75), font=("Helvetica", 12)), sg.FolderBrowse(initial_folder=basePath, font=("Helvetica", 16)) ]] file_listbox_elem = sg.Listbox(values=img_fileNames, size=(40, 20), font=("Helvetica", 16), key='listbox') # define layout, show and read the imageBrowser # Define the buttons: rightColumn = [[filename_display_elem], [resize_display_elem], [ sg.ReadFormButton('Prev', size=(6, 1), font=("Helvetica", 20)), sg.ReadFormButton('Next', size=(6, 1), font=("Helvetica", 20)), file_num_display_elem, sg.ReadFormButton('Color Image', size=(14, 1),
def behavior_window_handler(behavior_type: str, select: list): listbox_unit = sg.Listbox(list(UNIT.keys()), size=LISTBOX_SIZE, key='unit', enable_events=True) widgets = [ create_frame('Unit', [listbox_unit]), create_frame('Attributes', [ sg.Listbox([], key='attrs', enable_events=True, size=LISTBOX_SIZE) ]), create_frame( 'Operations', [sg.Listbox([], key='ops', enable_events=True, size=LISTBOX_SIZE) ]), create_frame('Attribute value', [ sg.InputCombo( [""], disabled=True, key="attr_value", size=(100, 20)) ]), create_frame('Actions', [ sg.Listbox( [], key='actions', enable_events=True, size=LISTBOX_SIZE) ]), create_frame('Action value', [sg.InputText("0", disabled=True, key='action_value')]), create_frame('Action duration', [sg.InputText("0", disabled=True, key='action_duration')]) ] behavior_window = sg.Window("Add behavior", layout=[ widgets, [ sg.Button('Add', key='+_behavior', size=BUTTON_SIZE), sg.CloseButton('Close', key='Close_behavior', size=BUTTON_SIZE) ] ]) behavior_window.Finalize() while True: event, values = behavior_window.Read() if event == '+_behavior': key = all_behavior[behavior_type]['counter'] tree = all_behavior[behavior_type]['tree_data'] behavior_tree = all_behavior[behavior_type]['tree'] storage = all_behavior[behavior_type]['storage'] selected = all_behavior[behavior_type]['select'] key.increment() new_values = { k: v[0] if not isinstance(v, str) else v for k, v in values.items() if v } if select: for i in select: tree.Insert(i, str(key.count), convert_text(str(key.count), new_values), values) else: tree.Insert(select, str(key.count), convert_text(str(key.count), new_values), values) behavior_tree.Update(tree) parents = selected.Values parents.append(str(key.count)) selected.Update(values=parents, disabled=False) storage.insert(select, str(key.count), new_values) elif event == 'Close_behavior': break elif event == 'unit': vals = list(ATTRIBUTES[values['unit'][0]].keys()) widgets[1].Rows[0][0].Update(vals) elif event == 'attrs': attrs = values.get('attrs', None) if attrs: widgets[3].Rows[0][0].Update(values=ATTR_VALUES[attrs[0]], disabled=False) widgets[2].Rows[0][0].Update(list(OPERATORS[attrs[0]].keys())) widgets[4].Rows[0][0].Update(list(ACTIONS.keys())) elif event == 'actions': if values.get('actions', []): if values.get('actions', [''])[0] != 'do nothing': widgets[5].Rows[0][0].Update(disabled=False) widgets[6].Rows[0][0].Update(disabled=False) else: widgets[5].Rows[0][0].Update(disabled=True) return
font="proximanova 16", background_color="transparent", text_color="#b3b3b3"), sg.Button('', image_data=settings, button_color=(sg.theme_background_color(), sg.theme_background_color()), border_width=0, key='settings', tooltip="Choose playlists to display below.") ], [ sg.Listbox(values=[" "], key="chosenplaylists", font="ProximaNova 13", size_px=(136, 90), select_mode='single', background_color="transparent", text_color=sg.theme_text_color()) ]] overlay = [[ sg.Column(playlist, element_justification="l"), sg.Column(header, element_justification="l") ], [ sg.Button('', image_data=notliked, button_color=(sg.theme_background_color(), sg.theme_background_color()), key='notliked',
def main(): sg.ChangeLookAndFeel('GreenTan') # sg.SetOptions(element_padding=(0,0)) # ------ Menu Definition ------ # menu_def = [ ['&File', ['&Open', '&Save', '&Properties', 'E&xit']], [ '&Edit', ['&Paste', [ 'Special', 'Normal', ], 'Undo'], ], ['&Toolbar', ['Command &1', 'Command &2', 'Command &3', 'Command &4']], ['&Help', '&About...'], ] treedata = sg.TreeData() treedata.Insert( "", '_A_', 'Tree Item 1', [1, 2, 3], ) treedata.Insert( "", '_B_', 'B', [4, 5, 6], ) treedata.Insert( "_A_", '_A1_', 'Sub Item 1', ['can', 'be', 'anything'], ) treedata.Insert( "", '_C_', 'C', [], ) treedata.Insert( "_C_", '_C1_', 'C1', ['or'], ) treedata.Insert("_A_", '_A2_', 'Sub Item 2', [None, None]) treedata.Insert("_A1_", '_A3_', 'A30', ['getting deep']) treedata.Insert("_C_", '_C2_', 'C2', ['nothing', 'at', 'all']) for i in range(100): treedata.Insert('_C_', i, i, []) frame1 = [ [sg.Input('Input Text', size=(250, 35)), sg.Stretch()], [ sg.Multiline(size=(250, 75), default_text='Multiline Input'), sg.MultilineOutput(size=(250, 75), default_text='Multiline Output') ], ] frame2 = [ [sg.Listbox(['Listbox 1', 'Listbox 2', 'Listbox 3'], size=(200, 85))], [ sg.Combo(['Combo item 1', 'Combo item 2', 'Combo item 3'], size=(200, 35)) ], [sg.Spin([1, 2, 3], size=(40, 30))], ] frame3 = [ [sg.Checkbox('Checkbox1', True), sg.Checkbox('Checkbox1')], [ sg.Radio('Radio Button1', 1), sg.Radio('Radio Button2', 1, default=True), sg.Stretch() ], ] frame4 = [ [ sg.Slider(range=(0, 100), orientation='v', size=(3, 30), default_value=40), sg.Dial(range=(0, 100), tick_interval=50, size=(150, 150), default_value=40), sg.Stretch() ], ] matrix = [[str(x * y) for x in range(4)] for y in range(3)] frame5 = [ [ sg.Table(values=matrix, max_col_width=25, auto_size_columns=True, display_row_numbers=True, change_submits=False, bind_return_key=True, justification='right', num_rows=8, alternating_row_color='lightblue', key='_table_', text_color='black'), sg.Tree(data=treedata, headings=['col1', 'col2', 'col3'], change_submits=True, auto_size_columns=True, num_rows=10, col0_width=10, key='_TREE_', show_expanded=True, size=(200, 150)), sg.Stretch() ], ] graph_elem = sg.Graph((880, 150), (0, 0), (600, 300), key='+GRAPH+') frame6 = [ [graph_elem, sg.Stretch()], ] tab1 = sg.Tab('Graph Number 1', frame6) tab2 = sg.Tab('Graph Number 2', [[]]) layout = [ [sg.Menu(menu_def)], [ sg.Image(data_base64=logo), sg.Frame('Input Text Group', frame1, title_color='red'), sg.Stretch() ], [ sg.Frame('Multiple Choice Group', frame2, title_color='green'), sg.Frame('Binary Choice Group', frame3, title_color='purple'), sg.Frame('Variable Choice Group', frame4, title_color='blue'), sg.Stretch() ], [ sg.Frame('Structured Data Group', frame5, title_color='red'), ], # [sg.Frame('Graphing Group', frame6)], [sg.TabGroup([[tab1, tab2]])], [ sg.ProgressBar(max_value=600, start_value=400, size=(600, 25), key='+PROGRESS+'), sg.Stretch(), sg.ButtonMenu('&Menu', ['Menu', ['&Pause Graph', 'Menu item']], key='_MENU_'), sg.Button('Button'), sg.Button('Exit') ], ] window = sg.Window('Window Title', font=('Helvetica', 13), default_button_element_size=(100, 30), auto_size_buttons=False, default_element_size=(200, 22)).Layout(layout).Finalize() graph_elem.DrawCircle((200, 200), 50, 'blue') i = 0 graph_paused = False while True: # Event Loop # sg.TimerStart() event, values = window.Read(timeout=0) if event is None or event == 'Exit': break if event == 'Button': print(event, values) if values['_MENU_'] == 'Pause Graph': graph_paused = not graph_paused if not graph_paused: i += 1 if i >= 600: graph_elem.Move(-1, 0) graph_elem.DrawLine((i, 0), (i, randint(0, 300)), width=1, color='#{:06x}'.format(randint(0, 0xffffff))) window.FindElement('+PROGRESS+').UpdateBar(i % 600) # sg.TimerStop() window.Close()
""" Define information for the 'Start New Game' window """ from ..popups import alerts import PySimpleGUIQt as qt frame1 = [ [qt.Listbox('')] ] window = qt.Window('') active = False
def displayImages(): sg.ChangeLookAndFeel('LightGrey') folder = sg.popup_get_folder('Image folder to open', title='Choose Folder', default_path='') img_types = (".png", ".jpg", "jpeg", ".tiff", ".bmp") flist0 = os.listdir(folder) fnames = [f for f in flist0 if os.path.isfile( os.path.join(folder, f)) and f.lower().endswith(img_types)] num_files = len(fnames) del flist0 def get_img_data(f, maxsize=(1200, 850), first=False): img = Image.open(f) img.thumbnail(maxsize) if first: bio = io.BytesIO() img.save(bio, format="PNG") del img return bio.getvalue() return ImageTk.PhotoImage(img) filename = os.path.join(folder, fnames[0]) image_elem = sg.Image(data=get_img_data(filename, first=True)) filename_display_elem = sg.Text(filename, size=(80, 3)) file_num_display_elem = sg.Text('File 1 of {}'.format(num_files), size=(15, 1)) col = [[filename_display_elem], [image_elem]] col_files = [[sg.Text('List of images')], [sg.Listbox(values=fnames, change_submits=True, size=(60, 10), key='listbox')], [sg.Button('Next', size=(8, 1)), sg.Button('Prev', size=(8, 1)), file_num_display_elem], [sg.Button('Enhance Resolution', size=(16, 1))], [sg.Button('Exit', size=(8, 1))]] layoutSavedImages = [[sg.Column(col_files), sg.Column(col)]] window = sg.Window('Image Browser', layoutSavedImages, return_keyboard_events=True, location=(0, 0), use_default_focus=False) i = 0 im = 0 while True: event, values = window.read() print(event, values) if event == sg.WIN_CLOSED or event == 'Exit': raise SystemExit() elif event in ('Next', 'MouseWheel:Down', 'Down:40', 'Next:34'): i += 1 if i >= num_files: i -= num_files filename = os.path.join(folder, fnames[i]) elif event in ('Prev', 'MouseWheel:Up', 'Up:38', 'Prior:33'): i -= 1 if i < 0: i = num_files + i filename = os.path.join(folder, fnames[i]) elif event == 'listbox': f = values["listbox"][0] filename = os.path.join(folder, f) i = fnames.index(f) elif event == 'Enhance Resolution': filename = os.path.join(folder, fnames[i]) super_res(filename, im) im += 1 print(filename) else: filename = os.path.join(folder, fnames[i]) image_elem.update(data=get_img_data(filename, first=True)) filename_display_elem.update(filename) file_num_display_elem.update('File {} of {}'.format(i+1, num_files)) window.close()
font=('Any', 14)) ], [ sg.Text('This is the new Dial Element'), sg.Dial(background_color='red'), sg.Stretch() ], [ sg.Combo(['Combo 1', 'Combo 2', 'Combo 3'], key='+COMBO+', size=(150, 30), text_color='green') ], [ sg.Listbox(['Listbox Item 1', 'Listbox Item 2', 'Listbox Item 3'], key='+LIST+', size=(200, 150), text_color='blue'), sg.Slider((1, 100), orientation='v', key='+SLIDER 1+') ], [ sg.Slider((1, 10), size=(200, 30), orientation='h', key='+SLIDER 2+'), sg.Stretch() ], [ sg.Checkbox('Checkbox 1', key='+CB1+'), sg.Checkbox('Checkbox 2', key='+CB2') ], [sg.Checkbox('Checkbox 3'), sg.Checkbox('Checkbox 4')], [sg.Radio('Radio1', group_id=1), sg.Radio('Radio2', group_id=1)],
def main(): # List to sort num_bars = DATA_SIZE[0] // (BAR_WIDTH + 1) arr = [DATA_SIZE[1] // num_bars * i for i in range(1, num_bars)] # Window layout graph = sg.Graph(GRAPH_SIZE, (0, 0), DATA_SIZE, background_color='#F5F6F4') layout = [[ sg.Text('Visualization', size=(30, 1), font=("Helvetica", 25), background_color='#8F90A0', text_color='#FFFFFF') ], [graph], [ sg.Button('Select sorting method', button_color=['#FFFFFF', '#35343B'], font=("Helvetica", 12)), sg.Button('Generate new array', button_color=['#FFFFFF', '#35343B'], font=("Helvetica", 12)) ]] window = sg.Window('Algorithm Visualizer', layout) window.Finalize() draw_bars(graph, arr) while True: event, values = window.read() if event in (None, 'Exit'): break if event == 'Generate new array': graph.Erase() random.shuffle(arr) draw_bars(graph, arr) if event == 'Select sorting method': l2 = [[ sg.T('Choose sorting method', font=("Helvetica", 12), background_color='#8F90A0', text_color='#FFFFFF') ], [ sg.Listbox(['Bubble', 'Insertion', 'Selection'], size=(16, 3)) ], [sg.Ok()]] w2 = sg.Window('Choose sorting method', l2) button, values = w2() w2.close() try: if values[0][0] == 'Bubble': sort = bubblesort.bubbleSort(arr) sortmethod = 'Bubble' elif values[0][0] == 'Insertion': sort = insertionsort.insertionSort(arr) sortmethod = 'Insertion' else: sort = selectionsort.selectionSort(arr) sortmethod = 'Selection' except: sg.Popup('None selected.', font=("Helvetica", 12), background_color='#8F90A0', text_color='#FFFFFF') continue timeout = 10 for partially_sorted_list in sort: event, values = window.read(timeout=timeout) if event is None: break graph.Erase() draw_bars(graph, partially_sorted_list) timeout = int(10) sg.Popup(f'{sortmethod} sort done.', font=("Helvetica", 12), background_color='#8F90A0', text_color='#FFFFFF')
[sg.Text('Widgets Currently Supported By PySimpleGUIQt')], [ sg.Text('Text', size=(200, 35)), sg.Text('Text In Any Color/Font', font=('Courier', 15), text_color='red') ], [sg.Text('Single Line Input', size=(200, 35)), sg.Input(size=(200, 25))], [ sg.Text('Multi Line\nInput/Output', size=(200, 60)), sg.Multiline(size=(200, 75)) ], [ sg.Text('ListBox', size=(200, 35)), sg.Listbox(['Listbox 1', 'Listbox 2', 'Listbox 3'], size=(200, 85)) ], [ sg.Text('ComboBox / Dropdown', size=(200, 25)), sg.Combo([ 'Combo item 1', ], size=(200, 35)) ], [sg.Text('Spinner', size=(200, 35)), sg.Spin([1, 2, 3], size=(40, 30))], [ sg.Text('Checkbox', size=(200, 35)), sg.Checkbox('Checkbox', change_submits=True) ], [sg.Text('RadioButton', size=(200, 35)), sg.Radio('Radio Button', 1)], [sg.Text('Slider', size=(200, 35)), sg.Slider(orientation='h')],
[sg.Text('Font:'), sg.Text('QS:')], [ sg.Input(do_not_clear=True, enable_events=False, focus=False, key='_FONT_'), sg.Input(do_not_clear=True, enable_events=False, focus=False, key='_QS_') ], [sg.Button('Refresh'), sg.Exit()], [ sg.Listbox(values=char_list_symbol, size=(15, 5.5), key='_LISTBOX_', enable_events=True, select_mode='single', auto_size_text=True), sg.Listbox(values=[], size=(8, 5.5), key='_MARKERTYPE_', enable_events=True, default_values=None, select_mode='single'), sg.Listbox(values=list_type, size=(20, 5.5), key='_LISTTYPE_', enable_events=True, default_values=None, select_mode='single') ],
import requests import lxml import PySimpleGUIQt as sg sg.theme('Reddit') headings = [ 'Nome', 'Seeders', 'Leechers', 'Data', 'Tamanho', 'Usuário', 'Download' ] l = ['', '', '', '', '', '', ''] Values = [l for a in range(20)] Layout = [[ sg.T("Procurar:"), sg.I(key='keywords'), sg.B("PROCURAR", key='PROCURAR', size=(10, 1)) ], [sg.Listbox(l, enable_events=True, key='tabela')]] # [sg.Table(Values, headings=headings, key='tabela', auto_size_columns=True, enable_events=True)]] Window = sg.Window("1337x.to Searcher", layout=Layout, size=(1200, 695), font="SEGOEUI 11") while True: event, values = Window.read() print(event, values) if event is None or event == 'sair': break if event == 'PROCURAR': KEYWORD = Window['keywords'].Get() if KEYWORD not in ['', ' ', None]:
], [sg.Text("Whitelist:", size=(15, 1)), sg.InputText(key="_wl_", size=(37, 1))], [ sg.Text("Whitelist Regex:", size=(15, 1)), sg.InputText(key="_wl_regex_", size=(37, 1)), ], [sg.Text("Logfile:", size=(15, 1)), sg.InputText(key="_log_", size=(37, 1))], ], ) frm_data = sg.Frame( title="Data:", layout=[ [sg.Text("All Files:", size=(26, 1)), sg.Text("Filtered Files:", size=(26, 1))], [ sg.Listbox(values=("one", "two", "three"), size=(24, 5)), sg.Listbox(values=("one", "two", "three"), size=(24, 5)), ], ], ) tab_tools_convert = sg.Tab( "Convert", [ [sg.Button("WAV", key="_convert_to_wav_", size=(47, 1))], [sg.Button("MP3", key="_convert_to_mp3_", size=(47, 1))], [sg.Button("OGG", key="_convert_to_ogg_", size=(47, 1))], [sg.Button("FLAC", key="_convert_to_flac_", size=(47, 1))], [sg.Button("RAW", key="_convert_to_raw_", size=(47, 1))], ], )
count+=1 if (update_index): self.current_index = count LISTBOX_SMALL = 3 LISTBOX_BIG = 5 first_session = session_manager(session(loaded)) second_session = session_manager(None) search_info = search_manager() layout = [[sg.Text('Session to add from')], [sg.In(default_text=get_session(), size=(80, 1), key='Session2'), sg.FileBrowse(), sg.Button('Choose', key="Choose Second")], [sg.Listbox(values=[], size=(30, LISTBOX_SMALL), select_mode=sg.LISTBOX_SELECT_MODE_EXTENDED, key='_WIN2', enable_events=True), sg.Listbox(values=[], size=(60, LISTBOX_SMALL), select_mode=sg.LISTBOX_SELECT_MODE_EXTENDED, key='_TAB2', enable_events=True), sg.Listbox(values=[], size=(30, LISTBOX_SMALL), select_mode=sg.LISTBOX_SELECT_MODE_EXTENDED, key='_HIS2', enable_events=True)], [sg.Button('Add Window(s)'), sg.Button( 'Add Tab(s)'), sg.Button('Add History')], [sg.Text('Session to add to')], [sg.In(default_text=get_session(), size=(80, 1), key='Session1'), sg.FileBrowse(), sg.Button('Choose')], [sg.Listbox(values=first_session.m_session.window_listbox, size=(30, LISTBOX_BIG), select_mode=sg.LISTBOX_SELECT_MODE_EXTENDED, key='_WIN', enable_events=True), sg.Listbox(values=[], size=(60, LISTBOX_BIG), select_mode=sg.LISTBOX_SELECT_MODE_EXTENDED, key='_TAB', enable_events=True), sg.Listbox(values=[], size=(30, LISTBOX_BIG), select_mode=sg.LISTBOX_SELECT_MODE_EXTENDED, key='_HIS', enable_events=True)],
['Дефолтность портфеля', '60315', 'oitga', '91315', 'iitg'], ['Доходность выдач', '47502', 'oitga', '91315', 'oitgp'] ] layout1 = [ [ sg.Frame('Номера банков', [[ sg.Text('№, №'), sg.InputText('1481', key='-REGNUMS-'), ]] ) ], [sg.Button('Настройки парсинга')], [ sg.Frame('Список банков', [[ sg.Listbox(values=[], select_mode=sg.LISTBOX_SELECT_MODE_MULTIPLE, key='-LISTBOX-') ]] ) ], [sg.Button('Взять данные'), sg.Text(' ' * 79), sg.Button('Удалить')], [ sg.Frame('Cохранение', [[ sg.FolderBrowse('Выберете папку', target='-PATH-'), sg.InputText(f'{dirname(__file__)}', key='-PATH-'), sg.Button('Сохранить') ]] ) ], [sg.ProgressBar(1000, orientation='h', key='progressbar')] ]
def pick_a_TC(instrument): ''' Graphical User interface - prompts the user for instrument, command and value then calls MakeTCfile to assemble the TC file based on the users choices ''' params, enums, defaults, num_vals, val_max, val_min, notes = read_parameter_file( tc_filename, instrument) param_layout = [[ sg.Listbox(values=params, key='_param_', tooltip='Select command to send', size=(20, 6), font=Font) ]] #param_layout = [[sg.InputCombo(values=params, key = '_param_', font = Font)]] layout_pick_parameter = [ [sg.Frame('Select Parameter to Update: ', param_layout, font=Font)], #[sg.Frame('Input new value: ', value_layout, font = Font)], [ sg.Submit(font=Font, pad=(10, 10)), sg.Cancel(font=Font, pad=(10, 10)) ] ] param_window = sg.Window('Select Parameter', layout_pick_parameter) event, values = param_window.Read() param_window.Close() tcString = values['_param_'][0] print(tcString) indx = 0 enumeration = 999 for words in params: if words == tcString: enumeration = enums[indx] break else: indx += 1 if num_vals[indx] == 0: confirm_layout = [[sg.Text('Confirm: ' + notes[indx], font=Font)], [ sg.Submit(pad=(10, 10), font=Font), sg.Cancel(pad=(10, 10), font=Font) ]] confirm_window = sg.Window('Confirm Command', confirm_layout) event, values = confirm_window.Read() confirm_window.Close() if event is None or event == 'Cancel': return None, None if event == 'Submit': filename = instrument + time.strftime("%Y%m%d-%H%M%S") + '.tc' cmnd = str(enumeration) + ';' MakeTCFile(filename, cmnd) send_layout = [[ sg.Text('Command is valid: ' + cmnd + '. Save or send now', font=Font) ], [ sg.Button(button_text='Save TC File', pad=(10, 10), font=Font), sg.Button(button_text='Send TC to CCMz', pad=(10, 10), font=Font) ]] send_window = sg.Window('Send TC', send_layout) event, values = send_window.Read() send_window.Close() if event == 'Send TC to CCMz': desc = notes[indx].split(':')[0] SendTC(filename, instrument, desc) else: sg.Popup('Values within range \nWriting ' + cmnd + '\nTo: ' + instrument + ' TC file: ' + filename, font=Font) return True, 0, filename if num_vals[indx] == 1: value_layout = [ [sg.Text(notes[indx], font=Font)], [sg.Text('Default Value ' + str(defaults[indx]), font=Font)], [sg.Text('Value:', font=Font), sg.InputText(key='_val_')] ] layout_enter_value = [[ sg.Frame('Input new value: ', value_layout, font=Font) ], [ sg.Submit(font=Font, pad=(10, 10)), sg.Cancel(font=Font, pad=(10, 10)) ]] value_window = sg.Window('Enter Value', layout_enter_value) event, values = value_window.Read() value_window.Close() new_param_value = float(values['_val_']) print(new_param_value) if new_param_value < float(val_max[indx]) and new_param_value > float( val_min[indx]): print('New value is within range') else: sg.Popup('Value(s) out of Range!\nNo TC File Created', font=Font) print('New Value out of Range!') return 'error', 0 filename = instrument + time.strftime("%Y%m%d-%H%M%S") + '.tc' cmnd = str(enumeration) + ',' + str(new_param_value) + ';' MakeTCFile(filename, cmnd) send_layout = [[ sg.Text('Command is valid: ' + cmnd + '. Save or send now', font=Font) ], [ sg.Button(button_text='Save TC File', pad=(10, 10), font=Font), sg.Button(button_text='Send TC to CCMz', pad=(10, 10), font=Font) ]] send_window = sg.Window('Send TC', send_layout) event, values = send_window.Read() send_window.Close() if event == 'Send TC to CCMz': desc = notes[indx].split(':')[0] + ': ' + str(new_param_value) SendTC(filename, instrument, desc) else: sg.Popup('Values within range \nWriting ' + cmnd + '\nTo: ' + instrument + ' TC file: ' + filename, font=Font) return True, 1, filename if num_vals[indx] == 2: value_layout = [ [sg.Text(notes[indx], font=Font)], [ sg.Text('Default Value ' + str(defaults[indx]) + 'No Limit Checking for values!', font=Font) ], [sg.Text('Value 1:', font=Font), sg.InputText(key='_val1_')], [sg.Text('Value 2:', font=Font), sg.InputText(key='_val2_')] ] layout_enter_value = [[ sg.Frame('Input new value: ', value_layout, font=Font) ], [ sg.Submit(font=Font, pad=(10, 10)), sg.Cancel(font=Font, pad=(10, 10)) ]] value_window = sg.Window('Enter Value', layout_enter_value) event, values = value_window.Read() value_window.Close() new_param_value_1 = float(values['_val1_']) new_param_value_2 = float(values['_val2_']) if new_param_value_1 < int(val_max[indx]) and new_param_value_1 > int( val_min[indx]): print('Value one is within range') if new_param_value_2 < int(val_max[indx]) and new_param_value_2 > int( val_min[indx]): print('Value two is within range') else: sg.Popup('Value(s) out of Range!\nNo TC File Created', font=Font) print('Value out of Range!') return 'error', 0 filename = instrument + time.strftime("%Y%m%d-%H%M%S") + '.tc' cmnd = str(enumeration) + ',' + str(new_param_value_1) + ',' + str( new_param_value_2) + ';' MakeTCFile(filename, cmnd) send_layout = [[ sg.Text('Command is valid: ' + cmnd + 'save or send now', font=Font) ], [ sg.Button(button_text='Save TC File', pad=(10, 10), font=Font), sg.Button(button_text='Send TC to CCMz', pad=(10, 10), font=Font) ]] send_window = sg.Window('Send TC', send_layout) event, values = send_window.Read() send_window.Close() if event == 'Send TC to CCMz': desc = notes[indx].split(':')[0] + ': ' + str( new_param_value_1) + ',' + str(new_param_value_2) SendTC(filename, instrument, desc) else: sg.Popup('Values within range \nWriting ' + cmnd + '\nTo: ' + instrument + ' TC file: ' + filename, font=Font) return True, 2, filename if num_vals[indx] == 3: value_layout = [ [sg.Text(notes[indx], font=Font)], [ sg.Text('Default Value ' + str(defaults[indx]) + 'No Limit Checking for values!', font=Font) ], [sg.Text('Value 1:', font=Font), sg.InputText(key='_val1_')], [sg.Text('Value 2:', font=Font), sg.InputText(key='_val2_')], [sg.Text('Value 3:', font=Font), sg.InputText(key='_val3_')] ] layout_enter_value = [[ sg.Frame('Input new value: ', value_layout, font=Font) ], [ sg.Submit(font=Font, pad=(10, 10)), sg.Cancel(font=Font, pad=(10, 10)) ]] value_window = sg.Window('Enter Value', layout_enter_value) event, values = value_window.Read() value_window.Close() new_param_value_1 = int(values['_val1_']) new_param_value_2 = int(values['_val2_']) new_param_value_3 = int(values['_val3_']) if new_param_value_1 < int(val_max[indx]) and new_param_value_1 > int( val_min[indx]): print('Value one is within range') if new_param_value_2 < int(val_max[indx]) and new_param_value_2 > int( val_min[indx]): print('Value two is within range') if new_param_value_3 < int(val_max[indx]) and new_param_value_3 > int( val_min[indx]): print('Value three is within range') else: sg.Popup('Value(s) out of Range!\nNo TC File Created', font=Font) print('Value out of Range!') return 'error', 0 filename = instrument + time.strftime("%Y%m%d-%H%M%S") + '.tc' cmnd = str(enumeration) + ',' + str(new_param_value_1) + ',' + str( new_param_value_2) + ',' + str(new_param_value_3) + ';' MakeTCFile(filename, cmnd) send_layout = [[ sg.Text('Command is valid: ' + cmnd + '. Save or send now', font=Font) ], [ sg.Button(button_text='Save TC File', pad=(10, 10), font=Font), sg.Button(button_text='Send TC to CCMz', pad=(10, 10), font=Font) ]] send_window = sg.Window('Send TC', send_layout) event, values = send_window.Read() send_window.Close() if event == 'Send TC to CCMz': desc = notes[indx].split(':')[0] + ': ' + str( new_param_value_1) + ',' + str(new_param_value_2) + ',' + str( new_param_value_3) SendTC(filename, instrument, desc) else: sg.Popup('Values within range \nWriting ' + cmnd + '\nTo: ' + instrument + ' TC file: ' + filename, font=Font) return True, 3, filename if num_vals[indx] == 4: value_layout = [ [sg.Text(notes[indx], font=Font)], [ sg.Text('Default Value ' + str(defaults[indx]) + 'No Limit Checking for values!', font=Font) ], [sg.Text('Value 1:', font=Font), sg.InputText(key='_val1_')], [sg.Text('Value 2:', font=Font), sg.InputText(key='_val2_')], [sg.Text('Value 3:', font=Font), sg.InputText(key='_val3_')], [sg.Text('Value 4:', font=Font), sg.InputText(key='_val4_')] ] layout_enter_value = [[ sg.Frame('Input new value: ', value_layout, font=Font) ], [ sg.Submit(font=Font, pad=(10, 10)), sg.Cancel(font=Font, pad=(10, 10)) ]] value_window = sg.Window('Enter Value', layout_enter_value) event, values = value_window.Read() value_window.Close() new_param_value_1 = int(values['_val1_']) new_param_value_2 = int(values['_val2_']) new_param_value_3 = int(values['_val3_']) new_param_value_4 = int(values['_val4_']) if new_param_value_1 < int(val_max[indx]) and new_param_value_1 > int( val_min[indx]): print('Value one is within range') if new_param_value_2 < int(val_max[indx]) and new_param_value_2 > int( val_min[indx]): print('Value two is within range') if new_param_value_3 < int(val_max[indx]) and new_param_value_4 > int( val_min[indx]): print('Value three is within range') if new_param_value_4 < int(val_max[indx]) and new_param_value_3 > int( val_min[indx]): print('Value four is within range') else: sg.Popup('Value(s) out of Range!\nNo TC File Created', font=Font) print('Value out of Range!') return False, 0 filename = instrument + time.strftime("%Y%m%d-%H%M%S") + '.tc' cmnd = str(enumeration) + ',' + str(new_param_value_1) + ',' + str( new_param_value_2) + ',' + str(new_param_value_3) + ',' + str( new_param_value_4) + ';' MakeTCFile(filename, cmnd) send_layout = [[ sg.Text('Command is valid: ' + cmnd + 'save or send now', font=Font) ], [ sg.Button(button_text='Save TC File', pad=(10, 10), font=Font), sg.Button(button_text='Send TC to CCMz', pad=(10, 10), font=Font) ]] send_window = sg.Window('Send TC', send_layout) event, values = send_window.Read() send_window.Close() if event == 'Send TC to CCMz': desc = notes[indx].split(':')[0] + ': ' + str( new_param_value_1) + ',' + str(new_param_value_2) + ',' + str( new_param_value_3) + ',' + str(new_param_value_4) SendTC(filename, instrument, desc) else: sg.Popup('Values within range \nWriting ' + cmnd + '\nTo: ' + instrument + ' TC file: ' + filename, font=Font) return True, 4, filename if num_vals[indx] == 5: value_layout = [ [sg.Text(notes[indx], font=Font)], [ sg.Text('Default Value ' + str(defaults[indx]) + 'No Limit Checking for values!', font=Font) ], [sg.Text('Value 1:', font=Font), sg.InputText(key='_val1_')], [sg.Text('Value 2:', font=Font), sg.InputText(key='_val2_')], [sg.Text('Value 3:', font=Font), sg.InputText(key='_val3_')], [sg.Text('Value 4:', font=Font), sg.InputText(key='_val4_')], [sg.Text('Value 5:', font=Font), sg.InputText(key='_val5_')] ] layout_enter_value = [[ sg.Frame('Input new value: ', value_layout, font=Font) ], [ sg.Submit(font=Font, pad=(10, 10)), sg.Cancel(font=Font, pad=(10, 10)) ]] value_window = sg.Window('Enter Value', layout_enter_value) event, values = value_window.Read() value_window.Close() new_param_value_1 = int(values['_val1_']) new_param_value_2 = int(values['_val2_']) new_param_value_3 = int(values['_val3_']) new_param_value_4 = int(values['_val4_']) new_param_value_5 = int(values['_val5_']) if new_param_value_1 < int(val_max[indx]) and new_param_value_1 > int( val_min[indx]): print('Value one is within range') if new_param_value_2 < int(val_max[indx]) and new_param_value_2 > int( val_min[indx]): print('Value two is within range') if new_param_value_3 < int(val_max[indx]) and new_param_value_3 > int( val_min[indx]): print('Value three is within range') if new_param_value_4 < int(val_max[indx]) and new_param_value_4 > int( val_min[indx]): print('Value four is within range') if new_param_value_5 < int(val_max[indx]) and new_param_value_5 > int( val_min[indx]): print('Value four is within range') else: sg.Popup('Value(s) out of Range!\nNo TC File Created', font=Font) print('Value out of Range!') return False, 0 filename = instrument + time.strftime("%Y%m%d-%H%M%S") + '.tc' cmnd = str(enumeration) + ',' + str(new_param_value_1) + ',' + str( new_param_value_2) + ',' + str(new_param_value_3) + ',' + str( new_param_value_4) + ',' + str(new_param_value_5) + ';' MakeTCFile(filename, cmnd) send_layout = [[ sg.Text('Command is valid: ' + cmnd + '. Save or send now', font=Font) ], [ sg.Button(button_text='Save TC File', pad=(10, 10), font=Font), sg.Button(button_text='Send TC to CCMz', pad=(10, 10), font=Font) ]] send_window = sg.Window('Send TC', send_layout) event, values = send_window.Read() send_window.Close() if event == 'Send TC to CCMz': desc = notes[indx].split(':')[0] + ': ' + str( new_param_value_1) + ',' + str(new_param_value_2) + ',' + str( new_param_value_3) + ',' + str( new_param_value_4) + ',' + str(new_param_value_5) SendTC(filename, instrument, desc) else: sg.Popup('Values within range \nWriting ' + cmnd + '\nTo: ' + instrument + ' TC file: ' + filename, font=Font) return True, 5, filename
def the_gui(): """Starts and executes the GUI Returns when the user exits / closes the window """ ffmpeg_path = Path('ffmpeg_hevc.exe') settings_path = Path("settings.json") presets = { 0: "placebo", 1: "placebo", 2: "placebo", 3: "placebo", 4: "veryslow", 5: "slower", 6: "slow", 7: "medium", 8: "fast", 9: "faster", 10: "veryfast", 11: "superfast", 12: "ultrafast" } # queue used to communicate between the gui and the threads gui_queue = queue.Queue() encode_queue = queue.Queue() encode_list = [] encode_event = queue.Queue( ) # queue for handling when encodes finish and start # Define default settings to make it possible to generate settings.json settings = {"settings": {"theme": "Default1"}} status_deque = deque(maxlen=1) # deque for handling the status bar element check_paths(ffmpeg_path, gui_queue) # Load settings from json if it exist if settings_path.exists(): with settings_path.open() as file: settings = json.load(file) sg.change_look_and_feel(settings["settings"]["theme"]) else: print("Could not find settings.json") write_settings(settings_path, settings) tooltips = { # ENCODE "tune": "0 = visual quality, 1 = psnr/ssim, 2 = vmaf", "preset": "Trades speed for quality and compression.\n'Veryfast' and up only works for 1080p or higher, while 'ultrafast' and 'superfast' is 4k and higher only.\nYou might have a file that is just a few pixels away fitting 1080p, and you will be limited to the 'faster' preset or slower\nBest to stay around medium unless you have a godly pc/trash pc", "drc": "Enables variable bitrate. Lets the encoder vary the targeted quality. \nIf you are unsure, leave it off", "qmin": "Minimum quality level in DRC mode. Must be lower than qmax", "qmax": "Maximum quality level in DRC mode. Must be higher than qmin", "qp": "The quality the encoder will target. Lower values result in higher quality, but much larger filesize. \nUsually stay around 20 for h.264 content, but can often go lower for mpeg2 content. Recommend 22 or 23 for 1080p with high bitrate. \nExperiment with quality by enabling test encode!", # FILTERS "sharpen": "How much to sharpen the image with unsharp, with a moderate impact to encode speed. \nIt is usually a good idea to sharpen the image a bit when transcoding. I recommend about 0.2 to 0.3", # AUDIO "skip_audio": "Enable to skip all audio tracks. Disable to passthrough audio", # BUTTONS "pause_queue": "Once the queue is paused the current job will finish, but the next job will not be started.", "start_encode": "Add job to queue, start it if no encode is currently running.", # MISC "test_encode": "Only encode part of the video. Lets you compare quality of encode to source, and estimate filesize. \nSpecify how many frames, usually 1000 is enough" } params = { "input": "", "output": "", "skip_audio": "", "qp": 20, "subtitles": False, "enable_filters": "-vf", "drc": 0, "qmin": 19, "qmax": 21, "sharpen_mode": "", "crop": "", "tune": 0, "preset": 7, "test_encode": "", "n_frames": "1000", "start_time": "00:00:00.000", "end_time": "", } old_params = params.copy() video_metadata = { "contains_video": False, "frame_count": None, "size": None, "fps": None, "duration": None, "width": None, "height": None, } menu_def = [['&Settings', ['&Themes', '!&Preferences', '---', 'E&xit']], ['&Presets', ['!&Save preset', '---', '!Preset1']]] drc_col = [ [ sg.Checkbox("Dynamic rate control", key="-DRC-", enable_events=True, tooltip=tooltips["drc"]) ], [ sg.Text("minQP", size=(5, 1), tooltip=tooltips["qmin"]), sg.Spin([i for i in range(1, 51)], initial_value=params["qmin"], key="-QMIN-", size=(5, 1), enable_events=True, disabled=True, tooltip=tooltips["qmin"]), sg.Text("maxQP", size=(5, 1), tooltip=tooltips["qmax"]), sg.Spin([i for i in range(1, 51)], initial_value=params["qmax"], key="-QMAX-", size=(5, 1), enable_events=True, disabled=True, tooltip=tooltips["qmax"]), ], ] encoding_col = [ [ sg.Column([ [sg.Text("Quality", tooltip=tooltips["qp"])], [ sg.Text("QP", size=(2, 1)), sg.Spin([i for i in range(1, 51)], initial_value=params["qp"], key="-QP-", size=(5, 1), enable_events=True, tooltip=tooltips["qp"]) ], ]), sg.VerticalSeparator(), sg.Column(drc_col), sg.VerticalSeparator(), sg.Column([[ sg.Text("Preset (medium)", size=(10, 1), key="-PRESET_TEXT-", tooltip=tooltips["preset"]) ], [ sg.Slider(range=(0, 12), default_value=7, orientation="horizontal", key="-PRESET-", enable_events=True, tooltip=tooltips["preset"]) ]]), # sg.Column([[sg.Text("Tune", size=(5, 1), tooltip=tooltips["tune"])], [sg.DropDown([0, 1, 2], default_value=0, key="-TUNE-", enable_events=True, tooltip=tooltips["tune"])]]) # Tune is no longer an option ], ] audio_col = [[ sg.Checkbox("Skip audio", key="-AUDIO-", enable_events=True, default=False, tooltip=tooltips["skip_audio"]) ]] def range_with_floats(start, stop, step): """Func for generating a range of decimals""" while stop > start: yield round( start, 2) # adding round() to our function and rounding to 2 digits start += step filter_col = [[ sg.Checkbox("Sharpen", key="-SHARP_CONTROL-", size=(8, 1), enable_events=True, tooltip=tooltips["sharpen"]), sg.Spin([i for i in range_with_floats(-1.50, 1.50, 0.05)], key="-SHARPEN-", initial_value=0.25, size=(6, 1), enable_events=True, disabled=True, tooltip=tooltips["sharpen"]) ]] video_col = [[ sg.T("Resolution"), sg.Input(default_text="WDxHG", disabled=True, key="-RESOLUTION-"), sg.T("Crop"), sg.Input(key="-CROP-", enable_events=True), sg.Button("Autocrop") ]] layout = [ [sg.Menu(menu_def)], [sg.Text("Browse or drag n drop video file")], [ sg.Text("Input"), sg.Input(key="-INPUT-", enable_events=True), sg.FileBrowse(enable_events=True) ], # [ sg.Text("Output"), sg.Input(key="-OUTPUT-", enable_events=True), sg.SaveAs(enable_events=True) ], [sg.Frame("Encode options", encoding_col)], [ sg.Frame("Audio options", audio_col), sg.Frame("Filters", filter_col) ], [sg.Frame("Video", video_col)], [ sg.Frame("Misc", [[ sg.Checkbox("Test encode (n frames)", size=(16, 1), key="-TEST_ENCODE-", enable_events=True, tooltip=tooltips["test_encode"]), sg.Input(default_text=params["n_frames"], size=(5, 1), enable_events=True, key="-TEST_FRAMES-", disabled=True, tooltip=tooltips["test_encode"]) ], [ sg.T("Start time", size=(7, 1)), sg.Input(default_text=params["start_time"], enable_events=True, key="-START_TIME-", size=(9, 1), tooltip="Start timestamp"), sg.T("End time", size=(6, 1)), sg.Input(default_text="00:00:00.000", enable_events=True, key="-END_TIME-", size=(9, 1), tooltip="End timestamp") ]]) ], # [sg.Frame("Command", [[sg.Column([[sg.Multiline(key="-COMMAND-", size=(60, 3))]])]])], [ sg.Frame("Queue", [[ sg.Column([[sg.Listbox(values=[], key="-QUEUE_DISPLAY-")], [ sg.Button("Remove task", size=(15, 1)), sg.Button("UP", size=(7, 1)), sg.Button("DOWN", size=(7, 1)) ]]) ]]) ], [ sg.Button("Start encode / add to queue", key="Start encode", size=(20, 1), tooltip=tooltips["start_encode"]), sg.Button("Stop encode", size=(20, 1)), sg.Button("Pause queue", key="Pause queue", size=(20, 1), tooltip=tooltips["pause_queue"]) ], [sg.T("", key="-STATUS_BOX-")], [sg.Output()], # Disable this line to get output to the console # [sg.ProgressBar(100, key="-PROGRESSBAR-")], [sg.Button('Exit')], ] window = sg.Window('SVT_GUI', layout) encoder = threading.Thread(target=encode_thread, args=(encode_queue, gui_queue, status_deque, encode_event), daemon=True) try: encoder.start() except Exception as e: print('Error starting work thread. Bad input?\n ' + str(e)) encode_queue_active.set() # Start active # progressbar = window["-PROGRESSBAR-"] def update_command(): window["-COMMAND-"].update(' '.join(format_command())) def format_command(): input_text = "" output_text = "" if params["input"] != "": input_path = Path(params["input"]) input_text = str(input_path) if params["output"] != "": output_path = Path(params["output"]) output_text = str(output_path) enable_filters = params[ "enable_filters"] if params["sharpen_mode"] != "" or params[ "crop"] else "" # todo: Add check for each filter here filters = ",".join( filter(None, [params["sharpen_mode"], params["crop"]])) print("filters: " + (filters if filters else "None")) n_frames = params["n_frames"] if params[ "test_encode"] != "" else "" # Disable vframes number if we dont want to do test encode # Filter list before return to remove empty strings return list( filter(None, [ "-i", input_text, "-y", "-ss", params["start_time"], ("-to" if params["end_time"] else ""), params["end_time"], "-sn", params["skip_audio"], "-map", "0", enable_filters, filters, "-c:v", "libsvt_hevc", params["test_encode"], n_frames, "-rc", str(params["drc"]), "-qmin", str(params["qmin"]), "-qmax", str(params["qmax"]), "-qp", str(params["qp"]), "-preset", str(params["preset"]), output_text ])) def toggle_queue(): if encode_queue_active.is_set(): encode_queue_active.clear() window.Element("Pause queue").update("Unpause Queue") else: encode_queue_active.set() window.Element("Pause queue").update("Pause Queue") def pause_queue(): if encode_queue_active.is_set(): encode_queue_active.clear() window.Element("Pause queue").update("Unpause Queue") def autocrop(): try: # TODO: If the video is shorter than around 16 seconds we might not get any crop values because of the low framerate and start time start_time = int( (video_metadata["duration"] / 4) / 1000) # Start detecting crop at 1/4 of the video duration command = [ ffmpeg_path.absolute().as_posix(), "-ss", str(start_time), "-i", str(Path(params["input"])), "-t", "01:20", "-vsync", "vfr", "-vf", "fps=0.2,cropdetect", "-f", "null", "-" ] process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True, close_fds=True) # out, err = process.communicate() crop_values = [] for line in process.stdout: # print(line) if "crop=" in line: crop_values.append(line.split("crop=")[1]) if len(crop_values) > 0: most_common = max(set(crop_values), key=crop_values.count) print("CROP: " + most_common) if most_common: return most_common else: print("Could not generate a crop :(") return "" except Exception as ex: print(ex.args) print("Could not generate a crop :(") return "" def update_queue_display(): window.Element("-QUEUE_DISPLAY-").update(values=[ i["status"] + " | " + i["title"] + " - " + i["uuid"] for i in encode_list ]) def build_encode_queue(): clear_queue(encode_queue) for i in encode_list: if i["status"] == "⏱ waiting": encode_queue.put(i) # # # --------------------- EVENT LOOP --------------------- # while True: event, values = window.read(timeout=100) if event in (None, 'Exit'): break elif event == "-INPUT-": window.Element("-INPUT-").update( background_color="white") # Reset background color file_string = values["-INPUT-"].replace("file:///", "") input_file = Path(file_string) if input_file.exists() and input_file.is_file(): params["input"] = input_file.absolute() # Update params # Fill in output based on folder and filename of input new_file = input_file while new_file.exists(): new_file = Path( new_file.with_name(new_file.stem + "_new.mkv")) params["output"] = str(new_file.absolute()) window.Element("-OUTPUT-").update(str(new_file.absolute())) print("** Analyzing input using mediainfo... **") media_info = MediaInfo.parse(str(input_file.absolute())) for track in media_info.tracks: if track: if track.track_type == "General": video_metadata["name"] = track.file_name_extension elif track.track_type == 'Video': video_metadata["contains_video"] = True video_metadata["frame_count"] = track.frame_count video_metadata["size"] = int( track.stream_size ) / 1048576 if track.stream_size else None # in MiB video_metadata["fps"] = track.frame_rate video_metadata["width"] = track.width video_metadata["height"] = track.height # Reset the start and end time params params["end_time"] = "" params["start_time"] = "00:00:00.000" if track.height and track.width: window.Element("-RESOLUTION-").update( "%ix%i" % (track.width, track.height)) if track.duration: video_metadata["duration"] = float( track.duration) # hours, rem = divmod(float(track.duration), 3600) # minutes, seconds = divmod(rem, 60) milliseconds = float(track.duration) seconds = (milliseconds / 1000) % 60 minutes = int( (milliseconds / (1000 * 60)) % 60) hours = int( (milliseconds / (1000 * 60 * 60)) % 24) formatted_duration = "{:0>2}:{:0>2}:{:06.3f}".format( hours, minutes, seconds) print("Duration:", formatted_duration) window.Element("-END_TIME-").update( disabled=False) window.Element("-END_TIME-").update( formatted_duration) else: window.Element("-END_TIME-").update( disabled=True) if video_metadata["frame_count"] is None and video_metadata[ "contains_video"]: print( "Could not extract frame count, will not be able to report progress %" ) if not video_metadata["contains_video"]: print( "This file is either not a video file or does not contain a video stream." ) window.Element("-INPUT-").update(background_color="red") print('** Analyze done **') else: print("Can't find file: " + str(input_file.absolute())) elif event == "-OUTPUT-": if values[ "-OUTPUT-"] == "": # If the user clicks the saveAs button and cancels, the output string will be empty. Better to keep the old value in that case window.Element("-OUTPUT-").update(params["output"]) else: file_string = values["-OUTPUT-"].replace("file:///", "") params["output"] = file_string ################## # ENCODE SETTINGS elif event == "-QP-": params["qp"] = values["-QP-"] elif event == "-DRC-": val = values["-DRC-"] if val: params["drc"] = 1 window.Element("-QMIN-").update(disabled=False) window.Element("-QMAX-").update(disabled=False) window.Element("-QP-").update(disabled=True) else: params["drc"] = 0 window.Element("-QMIN-").update(disabled=True) window.Element("-QMAX-").update(disabled=True) window.Element("-QP-").update(disabled=False) elif event == "-PRESET-": # TODO: handle limiting preset by resolution as per https://github.com/OpenVisualCloud/SVT-HEVC/blob/master/Docs/svt-hevc_encoder_user_guide.md#encoding-presets-table window.Element("-PRESET_TEXT-").update("Preset ({})".format( presets[values["-PRESET-"]])) params["preset"] = values["-PRESET-"] elif event == "-TEST_ENCODE-": val = values["-TEST_ENCODE-"] if val: window.Element("-TEST_FRAMES-").update(disabled=False) params["test_encode"] = "-vframes" else: window.Element("-TEST_FRAMES-").update(disabled=True) params["test_encode"] = "" elif event == "-TEST_FRAMES-": val = ''.join( i for i in values["-TEST_FRAMES-"] if i.isdigit()) # Remove any non numbers from the input window.Element("-TEST_FRAMES-").update(val) params["n_frames"] = val elif event == "-START_TIME-": params["start_time"] = values["-START_TIME-"] elif event == "-END_TIME-": params["end_time"] = values["-END_TIME-"] ################## # AUDIO SETTINGS elif event == "-AUDIO-": if values["-AUDIO-"]: params["skip_audio"] = "-an" else: params["skip_audio"] = "" ################## # FILTER SETTINGS elif event == "-SHARPEN-": params["sharpen_mode"] = "unsharp=5:5:{}:5:5:{}".format( values["-SHARPEN-"], values["-SHARPEN-"]) elif event == "-CROP-": if values["-CROP-"]: params["crop"] = "crop=" + values["-CROP-"] else: params["crop"] = "" elif event == "-SHARP_CONTROL-": if values["-SHARP_CONTROL-"]: window.Element("-SHARPEN-").update(disabled=False) params["sharpen_mode"] = "unsharp=5:5:{}:5:5:{}".format( values["-SHARPEN-"], values["-SHARPEN-"]) else: window.Element("-SHARPEN-").update(disabled=True) params["sharpen_mode"] = "" ################## # QUEUE BUTTONS elif event == "Remove task": if values["-QUEUE_DISPLAY-"]: for queue_item in values[ "-QUEUE_DISPLAY-"]: # TODO: make alternative to nesting loops job_id = queue_item.split()[-1] for i, job in enumerate(encode_list): if job["uuid"] == job_id and job[ "status"] != "▶ started": encode_list.pop(i) build_encode_queue() update_queue_display() elif event == "UP": if values["-QUEUE_DISPLAY-"] and len( values["-QUEUE_DISPLAY-"]) == 1 and len(encode_list) > 1: job_id = values["-QUEUE_DISPLAY-"][0].split()[-1] for i, job in enumerate(encode_list): if job["uuid"] == job_id and i != 0: encode_list.insert(i - 1, encode_list.pop(i)) build_encode_queue() update_queue_display() elif event == "DOWN": if values["-QUEUE_DISPLAY-"] and len( values["-QUEUE_DISPLAY-"]) == 1 and len(encode_list) > 1: job_id = values["-QUEUE_DISPLAY-"][0].split()[-1] for i, job in enumerate(encode_list): if job["uuid"] == job_id and i != len(encode_list) - 1: encode_list.insert(i + 1, encode_list.pop(i)) build_encode_queue() update_queue_display() ################## # OTHER INTERACTS elif event == "Start encode": if not params["input"] or params["input"] == "": print("Missing input") elif not params["output"] or params["output"] == "": print("Missing output") elif not video_metadata["contains_video"]: print( "Cannot start encode because input file does not have a video track" ) else: finished_command = [ffmpeg_path.absolute().as_posix() ] + format_command() try: job_id = uuid.uuid4().hex encode_list.append({ "title": video_metadata["name"], "uuid": job_id, "status": "⏱ waiting", "output_file": Path(params["output"]), "command": finished_command, "metadata": video_metadata, "test_encode": int(params["n_frames"]) if params["test_encode"] != "" else False }) build_encode_queue() update_queue_display() except Exception as e: # TODO: make this better. Is it even needed? print('Error adding job. Bad input?:\n "%s"' % finished_command) elif event == "Stop encode": if encoder is not None: stoprequest.set() pause_queue() elif event == "Pause queue": toggle_queue() encode_queue.put(_skip) elif event == "Autocrop": crop = autocrop() params["crop"] = "crop=" + crop window.Element("-CROP-").update(crop) elif event == "Themes": theme = run_themes_window() # Save theme if theme and settings_path.exists(): settings["settings"]["theme"] = theme write_settings(settings_path, settings) print("Changed theme to {}. Restart the program to apply.". format(theme)) try: window.Element("-STATUS_BOX-").update(status_deque.popleft()) except IndexError: pass # --------------- Check for incoming messages from threads --------------- try: message = gui_queue.get_nowait() except queue.Empty: # get_nowait() will get exception when Queue is empty message = None # break from the loop if no more messages are queued up try: # Check for job events event = encode_event.get_nowait() print(event) for i, job in enumerate(encode_list): if job["uuid"] == event["uuid"]: item = encode_list[i] item["status"] = event["event"] encode_list[i] = item update_queue_display() except queue.Empty: pass # if message received from queue, display the message in the Window if message: print("#> " + message) # Update display of the encode command # if params.items() != old_params.items(): # update_command() # old_params = params.copy() # We have reached the end of the program, so lets clean up. window.disable() window.refresh() # have to refresh window manually outside of event loop if encoder is not None: stoprequest.set() # Clear queue then add sentinel to make thread stop waiting clear_queue(encode_queue) encode_queue.put(_sentinel) encode_queue_active.set( ) # We have to make sure the encode queue is active for it to finish, if not it will keep waiting print("\n** Taking a sec to shut everything down... **\n") window.refresh() encoder.join() if encoder.is_alive(): print("Thread still alive! wtf") window.refresh() window.close()
[sg.Text("Oblige Executable")], [sg.InputText(default_text=configList[0], key="oblige", do_not_clear=True), sg.FileBrowse(target="oblige")], [sg.Text("Oblige Config")], [sg.InputText(default_text=configList[1], key="oblige_config", do_not_clear=True), sg.FileBrowse( target="oblige_config", file_types=(("Text Files", "*.txt"),))], [sg.Text("Source Port")], [sg.InputText(default_text=configList[2], key="source_port", do_not_clear=True), sg.FileBrowse(target="source_port")], [sg.Text("IWAD")], [sg.InputText(default_text=configList[3], key="iwad", do_not_clear=True), sg.FileBrowse( target="iwad", file_types=(("IWAD Files", "*.wad"),))] ] mod_layout = [ [sg.Listbox(key="pwads", values=pwadList, size=(50, 5))], [sg.FilesBrowse("Add", key="Add", target=( "Add"), enable_events=True, file_types=(("PWAD Files", "*.wad;*.pk3"),)), sg.Button("Remove"), sg.Button("Clear"), sg.Text("", visible=False), sg.Button("▲"), sg.Button("▼")] ] sessions_layout = [ [sg.Listbox(key="session_list", values=sessionsListBox, size=(50, 5))], [sg.Button("Select"), sg.InputText( default_text="", key="session_name", do_not_clear=True), sg.Button("Rename"), sg.Button("Delete")] ] layout = [ [sg.Frame("Game", game_layout)], [sg.Frame("PWADs", mod_layout)], [sg.Text("Arguments"), sg.InputText( default_text=configList[4], key="arguments", do_not_clear=True)],