2021-01-17 21:30:27 +00:00
import os . path
import subprocess
import sys
import PySimpleGUI as sg
"""
Demo Browser
Makes using the Demo Programs each even more powerful .
Now you can quickly filter and search to find the demo you need .
You can launch editing the demo using your favorite editor .
On first run , click settings button to enter location of your demo programs .
Filter the list of demos using :
* Search using filename
* Searching within the demo program ' s source code (like grep)
The basic file operations are
* Edit a file in your editor
* Run a file
* Filter file list
* Search in files
Additional operations
* Edit this file in editor
Copyright 2021 PySimpleGUI . org
"""
def get_demo_git_files ( ) :
"""
Get the files in the demo and the GitHub folders
Returns files as 2 lists
: return : two lists of files
: rtype : Tuple [ List [ str ] , List [ str ] ]
"""
2021-01-18 20:08:34 +00:00
demo_path = sg . user_settings_get_entry ( ' -demos folder- ' , ' . ' )
2021-01-17 21:30:27 +00:00
try :
demo_files = os . listdir ( demo_path )
except :
demo_files = [ ]
return demo_files
def find_in_file ( string ) :
"""
Search through the demo files for a string .
The case of the string and the file contents are ignored
: param string : String to search for
: return : List of files containing the string
: rtype : List [ str ]
"""
demo_path = sg . user_settings_get_entry ( ' -demos folder- ' )
demo_files = get_demo_git_files ( )
string = string . lower ( )
file_list = [ ]
for file in demo_files :
filename = os . path . join ( demo_path , file )
try :
with open ( filename , ' r ' ) as f :
for line in f . readlines ( ) :
if string in line . lower ( ) :
file_list . append ( file )
# print(f'{os.path.basename(file)} -- {line}')
except Exception as e :
pass
# print(e)
return list ( set ( file_list ) )
def settings_window ( ) :
"""
Show the settings window .
This is where the folder paths and program paths are set .
Returns True if settings were changed
: return : True if settings were changed
: rtype : ( bool )
"""
layout = [ [ sg . T ( ' Program Settings ' , font = ' DEFAIULT 18 ' ) ] ,
2021-01-18 20:08:34 +00:00
[ sg . T ( ' Path to Demos ' , size = ( 20 , 1 ) ) , sg . In ( sg . user_settings_get_entry ( ' -demos folder- ' , ' . ' ) , k = ' -DEMOS- ' ) , sg . FolderBrowse ( ) ] ,
2021-01-17 21:30:27 +00:00
[ sg . T ( ' Editor Program ' , size = ( 20 , 1 ) ) , sg . In ( sg . user_settings_get_entry ( ' -Editor Program- ' , ' ' ) , k = ' -EDITOR PROGRAM- ' ) , sg . FileBrowse ( ) ] ,
[ sg . T ( r " For PyCharm, Add this to your PyCharm main program ' s folder \ bin \ pycharm.bat " ) ] ,
[ sg . Combo ( sg . theme_list ( ) , sg . user_settings_get_entry ( ' -theme- ' , None ) , k = ' -THEME- ' ) ] ,
2021-01-18 20:08:34 +00:00
[ sg . B ( ' Ok ' , bind_return_key = True ) , sg . B ( ' Cancel ' ) ] ,
2021-01-17 21:30:27 +00:00
]
window = sg . Window ( ' Settings ' , layout )
event , values = window . read ( close = True )
if event == ' Ok ' :
sg . user_settings_set_entry ( ' -demos folder- ' , values [ ' -DEMOS- ' ] )
sg . user_settings_set_entry ( ' -Editor Program- ' , values [ ' -EDITOR PROGRAM- ' ] )
sg . user_settings_set_entry ( ' -theme- ' , values [ ' -THEME- ' ] )
return True
return False
# --------------------------------- Create the window ---------------------------------
def make_window ( ) :
"""
Creates the main window
: return : The main window object
: rtype : ( Window )
"""
theme = sg . user_settings_get_entry ( ' -theme- ' )
demo_files = get_demo_git_files ( )
if not theme :
theme = sg . OFFICIAL_PYSIMPLEGUI_THEME
sg . theme ( theme )
# First the window layout...2 columns
find_tooltip = " Find in file \n Enter a string in box to search for string inside of the files. \n File list will update with list of files string found inside. "
filter_tooltip = " Filter files \n Enter a string in box to narrow down the list of files. \n File list will update with list of files with string in filename. "
ML_KEY = ' -ML- ' # Multline's key
left_col = [
[ sg . Listbox ( values = demo_files , select_mode = sg . SELECT_MODE_EXTENDED , size = ( 40 , 20 ) , key = ' -DEMO LIST- ' ) ] ,
2021-01-24 18:08:24 +00:00
[ sg . Text ( ' Filter: ' , tooltip = filter_tooltip ) , sg . Input ( size = ( 25 , 1 ) , enable_events = True , key = ' -FILTER- ' , tooltip = filter_tooltip ) ,
sg . T ( size = ( 20 , 1 ) , k = ' -FILTER NUMBER- ' ) ] ,
2021-01-17 21:30:27 +00:00
[ sg . Button ( ' Run ' ) , sg . B ( ' Edit ' ) , sg . B ( ' Clear ' ) ] ,
2021-01-24 18:08:24 +00:00
[ sg . Text ( ' Find: ' , tooltip = find_tooltip ) , sg . Input ( size = ( 25 , 1 ) , enable_events = True , key = ' -FIND- ' , tooltip = find_tooltip ) ,
sg . T ( size = ( 20 , 1 ) , k = ' -FIND NUMBER- ' ) ] ]
2021-01-17 21:30:27 +00:00
right_col = [
[ sg . Multiline ( size = ( 70 , 21 ) , write_only = True , key = ML_KEY , reroute_stdout = True , echo_stdout_stderr = True ) ] ,
[ sg . Button ( ' Edit Me (this program) ' ) , sg . B ( ' Settings ' ) , sg . Button ( ' Exit ' ) ] ,
[ sg . T ( ' PySimpleGUI ver ' + sg . version . split ( ' ' ) [ 0 ] + ' tkinter ver ' + sg . tclversion_detailed , font = ' Default 8 ' , pad = ( 0 , 0 ) ) ] ,
]
# ----- Full layout -----
layout = [ [ sg . Text ( ' Demo Programs Browser ' , font = ' Any 20 ' ) ] ,
[ sg . T ( ' Click settings to specify location of demo files ' ) ] ,
sg . vtop ( [ sg . Column ( left_col , element_justification = ' c ' ) , sg . Col ( right_col , element_justification = ' c ' ) ] ) ]
# --------------------------------- Create Window ---------------------------------
window = sg . Window ( ' PySimpleGUI Demo Program Browser ' , layout , icon = icon )
sg . cprint_set_output_destination ( window , ML_KEY )
return window
# --------------------------------- Main Program Layout ---------------------------------
def main ( ) :
"""
The main program that contains the event loop .
It will call the make_window function to create the window .
"""
2021-01-18 20:08:34 +00:00
demo_path = sg . user_settings_get_entry ( ' -demos folder- ' , ' . ' )
2021-01-17 21:30:27 +00:00
editor_program = sg . user_settings_get_entry ( ' -Editor Program- ' , ' ' )
demo_files = get_demo_git_files ( )
window = make_window ( )
while True :
event , values = window . read ( )
if event == sg . WINDOW_CLOSED or event == ' Exit ' :
break
if event == ' Edit ' :
for file in values [ ' -DEMO LIST- ' ] :
sg . cprint ( f ' opening (in editor) ' , text_color = ' white ' , background_color = ' red ' , end = ' ' )
sg . cprint ( ' ' )
sg . cprint ( f ' { os . path . join ( demo_path , file ) } ' , text_color = ' white ' , background_color = ' purple ' )
execute_command_subprocess ( f ' { editor_program } ' , os . path . join ( demo_path , file ) )
elif event == ' Run ' :
sg . cprint ( ' Running Demo Programs.... ' , c = ' white on green ' , end = ' ' )
sg . cprint ( ' ' )
for file in values [ ' -DEMO LIST- ' ] :
sg . cprint ( os . path . join ( demo_path , file ) , text_color = ' white ' , background_color = ' purple ' )
run_py ( os . path . join ( demo_path , file ) )
elif event . startswith ( ' Edit Me ' ) :
sg . cprint ( f ' opening using { editor_program } \n This file - { __file__ } ' , text_color = ' white ' , background_color = ' green ' , end = ' ' )
execute_command_subprocess ( f ' { editor_program } ' , __file__ )
elif event == ' -FILTER- ' :
new_list = [ i for i in demo_files if values [ ' -FILTER- ' ] . lower ( ) in i . lower ( ) ]
window [ ' -DEMO LIST- ' ] . update ( new_list )
2021-01-24 18:08:24 +00:00
window [ ' -FILTER NUMBER- ' ] . update ( f ' { len ( new_list ) } files ' )
window [ ' -FIND NUMBER- ' ] . update ( ' ' )
2021-01-17 21:30:27 +00:00
elif event == ' -FIND- ' :
file_list = find_in_file ( values [ ' -FIND- ' ] )
window [ ' -DEMO LIST- ' ] . update ( sorted ( file_list ) )
2021-01-24 18:08:24 +00:00
window [ ' -FIND NUMBER- ' ] . update ( f ' { len ( file_list ) } files ' )
window [ ' -FILTER NUMBER- ' ] . update ( ' ' )
2021-01-17 21:30:27 +00:00
elif event == ' Settings ' :
if settings_window ( ) is True :
window . close ( )
window = make_window ( )
demo_path = sg . user_settings_get_entry ( ' -demos folder- ' )
editor_program = sg . user_settings_get_entry ( ' -Editor Program- ' )
demo_files = get_demo_git_files ( )
elif event == ' Clear ' :
window [ ' -FILTER- ' ] . update ( ' ' )
window [ ' -FIND- ' ] . update ( ' ' )
window [ ' -DEMO LIST- ' ] . update ( demo_files )
2021-01-24 18:08:24 +00:00
window [ ' -FILTER NUMBER- ' ] . update ( ' ' )
window [ ' -FIND NUMBER- ' ] . update ( ' ' )
2021-01-17 21:30:27 +00:00
window . close ( )
def run ( app_name , parm = ' ' ) :
execute_command_subprocess ( app_name , parm )
def run_py ( pyfile , parms = None ) :
if parms is not None :
execute_command_subprocess ( ' python ' , pyfile , parms )
else :
execute_command_subprocess ( ' python ' , pyfile )
def execute_command_subprocess ( command , * args , wait = False ) :
if sys . platform == ' linux ' :
arg_string = ' '
for arg in args :
arg_string + = ' ' + str ( arg )
sp = subprocess . Popen ( [ ' python3 ' + arg_string , ] , shell = True , stdout = subprocess . PIPE , stderr = subprocess . PIPE )
else :
expanded_args = ' ' . join ( args )
sp = subprocess . Popen ( [ command , expanded_args ] , shell = True , stdout = subprocess . PIPE , stderr = subprocess . PIPE )
if wait :
out , err = sp . communicate ( )
if out :
print ( out . decode ( " utf-8 " ) )
if err :
print ( err . decode ( " utf-8 " ) )
if __name__ == ' __main__ ' :
icon = b ' iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAMAAAD04JH5AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAAB69LymqOSm6LSq2OTSrOjS2Ox28RjqdQC6qSiy3Riu3UTisRzirVDi1STq0UiuyYz6pYz62ZCjDNyjQPzTAOxrIQinARTXDRzXBVEWsP1ieZ0OrSUaqV0S0SkOzVFKnSVKrWlK0W0iqZUWmcEe0a1eoZ1apclW0Z1uzd2G8X2W8Z2i3dXStdnS/ZHW7dkXCTEnCWVnDbF3Gc1zUc2bGbGjId2fRbWjQfnLFbnTGeHfReXu6hWzFgWzRgXfGhn3Jk3bShHvWkd5HPNhYJ9RWPtRbPdxVOtlbM9xdPM5iPNRjO9VsMtNoOttiPOFVNOVUPeNZNOJbPelVPelZN+pcO/ZYPeNjPeFqPOlgNOpiPfBkO8xcR85ZUtZOUNJXQdNcQtNcTNpTRdxVT9xdQ95cSdlbUsBgR8xkRctkTc1oQ81pS8tmVMtxTsx3XtVjQdRjStRoQtNqStxiRNtjSdxpQ9toS9NkU9diWdFqUtVsW9xiU9xlXN5uVtZzWsptZ8Z3Y8p2ddBuY9duat1qY9Nvcdh3Z+VOQ+NUROJcQ+NcSutTROlcQ+pdSuhdVPJcQ/FbS/heQvZbVuFhReJjSeJpRORpTOpiRepiS+toTeVlU/RhRfJhUuZnYeBvaeR4aoPCfN+Hb9eHfNmQfeaIbOKIeOWSefaHbP+Ia/CMffCSePigeoTHhovJmIjWiYXXl5HMnpbYmY3bp4fes5PHoJnapJzUspDhnozjpo3lspnjqaLTm6HOsaPYp7XOuLbduajkqavpuLTpt7f2uKvbwbLYw7nmx7f1ybjw1tqIhtiThtiSkNasnNuimeSLhOWPkOWThuicl/mdiPKbku6fouWjl+Oinuaom+ynl+yjmuqpl+qqm/OllfOlmPSqnf6mkvqhneekoPOho8buuNPtvtbd08bpyMro1cT2ysj109XozNXo2NHzydT52M/45tvs4tj8497+8eD6y+b82+bq6Of+5+n+9fnq7f/p//b96fv7+gAAAAAAAAAAAAAAAAAAAFSfM6AAAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAMlUlEQVR4Xu2Zf5gbRRnHtd5Fm+Z2FUQOuWQplXI+oAVqA0RrAKUlRGINlkCpei2b2EI1187eFUitBfFgc0nah5m7pFsFnvJD1FIseoDFk1/agj+wpz5gBX8geu31ODmtqb39J76zO5vb/Lzsnjw8Pt7nLpfZmcnMd99533dmc28rvMXMCJgRMCNgRsCMgP9tAQdv23jDTYm72JU9piPg5U29W8OB1O2Jl1mFHaYh4I+dS7NAbkeg8yCrsoF9AS9Ge6++Ik6k4BV9qVW/ZJXWsS3gwf4ORDAWZYQwRsqDrNoydgUc7EcwP8KEEEyQiJQh1mAVmwJeIaKI+5EoUiMggpbYVmBPwFDmk0QiWBaxjCmEoCsz9hTYE/D8J65FGIl0AegawGqQCE7YigWbS9DTK4LvYSwDhMjgiShIEnZsYNcJt9DVJ7Iowy8toQ4cxHZWwa6AAiEwM5HJdpm6AZGVDhTptaHAsoDvdr6gF76WvDqckqT1KJ3GCsnIEJNItJ4PrAoYikc3MgWbU6l+HN+AUql0HEFM2MsHFgUMZe7oiq86oF8kRImaPxtAUpdoNx9YEzCUuTIb6pNjTMHdq6Srli3PdgWxGKYxYScfWBJwMIEjIo5Eigq23JpQYitFBefAIe3lAysChhIkiNbnwsFcb2wnqwNe+OYd27YHtZiwkQ8sCBjKQKh3EEgAKEfE+1kt5bZLUdBuPmhcAKx/BHUoadKZjl8euqqXxYLG5kDKbj5oWMCDCpJgkfXNB0DdzA8oQ6uWs2rYnazlg0YFHFRg/4WtH8ysE+k03+W6LKuGPtbyQYMChjIQ4jAwmwWIJFiTxrrPsGrAWj5oTMBQZhlE2KT9gbDC2jTWrWDVOhbyQUMCaPzDmHTg4hKsSJh8oPDFHaxa62IlHzQiQIt/8D8RIr24CFev7mHNlJ1LWTWcUq3lgwYE6PFPj8B0/2fzYBRWzHe4k1XDMc1aPphaAIt/6t5wANquT4Px+juvW/cL1oXCqrHVfDClgPL4N5C7URabHbFn2aeuIElCokQM9IVCjeaDqQRUxL9BshulkC7g59rfQo8clrDYHQV3JXJOWwfIBy/qjTWZQkBl/BtQAYGM1unzLCsr35ACkQDuT8o5lDTyQWyKWKgvoEr8GyQlJDMLpAMPaO+Fu1cjyAeREJyUQQAAnw1M4Qd1BVSLfwMQkEW6BQgWmQ16yO04EMDZPv0jNB9k5cyf9cbq1BNQNf4NTALi6zsUtjt//bb77t+8ZmUoGzGeF3Aonam3CnUEVI9/gzQIwDGtI5yIyRLT+eD3PWtzESMfxHFIrqegtoAa8W8AFkihpNYzc6ccQoj5gcatX8ixfICVDrxi6aZXWUMltQWsJTiQow5QHSogpDthDCOZSOG7tQudjctYN+oHoXB6HauvpKaAAxIOk2SySgDqUAGi7gMgACfl7E3ahU5P0WkDSrQT51aad64Sagq4T1ke6I/KXWycCkwWiFILxFMbtQude4sCLsMdUnarYl6gEmoK+Bb+LFZWYwio6pRbAKVu1i50Xs6wbhi2ZUW+UrmPNVRQewlW5rCUISE2TgXlPkBKLHBAT0QUInXKOyTTMb6U2k741Y4QrGxdAcwCsAQ4SSKSdqGzJcW6YZF0hLaLNpyw8Oq6uCLKEhungnILJHHQdFDvLJ6S+5OQETt/xuorqS2g8OsglqW6YWj2gUwwtFa7otwiX8O6YVHJ9V1mfoopo46Awkubomh9hohyFpSw8YpsI2l5m54JaVsXkZcH2aPCq3clk8slSJ5hTDKhPvG62vdfX0Dhd4qMRAnSKaR1fdpJkiulZE4/mivhAF6jkO1Y7Nxyy/M7e2IdEgqI/ShAd9K+pck69z+FgMIfEtGuOJIkiRQfPAy2r4FjSlTrpYQiWAK3z0L+l3KpZSmC+7owkrrhZIrE5Le1TrWoL6Bw8MYuFCaK1FEhAF8vhkTdAgmEIQzBEXB2WzoUwtlsYAnCS7qJiLPBWN37n1JA4SVRTOeIJOlfQJgIdy3LYj37dorgI1ERRTBOydev6QbL00dERFLp3BLzM2w1phJQeGXTdWkR9VfsCcuVVA6t1LpsRCRL4BCIYE/syyiZKEReQIaDVHq18U1GbaYUUPgLxEJQqjgShVFauuF5rcdmMLgIpodlJyiZThMZToMEB7O52K+0DvWYWkDhFQShVMztDEKWJNd+R+/wpw3BnNSH5VQ6mU6GgigudUpSBuHgpVPef0MCCi/dGEXx8nwgEXHytPm5yRUyx38D8zckAB4O5K7yfCAFvsJagQMKOKCOHv94yvg3aEhAtXwgyeYt3pSytfiPTxn/Bo0JqJIPxCxr0ohN+miD8W/QoIDKfIAwa9FITApoMP4NGhVQkQ9KlyBWPDc0Gv8GDQsozwdlTlgU0Gj8GzQuoDQfEClpCsMYKgpoNP4NLAgoyQeQ8ZKJ37CGHoR30PiHJ6SG49/AioCSfBDNKdKaL9P/Gj/wJXj8Ehvd/8uxJMCcD4gcwKHLN2zevGEJPA/T3bix/b8cawIm80GOJAOhvh2pT4evyV67IhtbZTX+DSwKmMwHYl
main ( )