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__ ' :
2021-01-24 18:24:45 +00:00
icon = b ' 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
2021-01-17 21:30:27 +00:00
main ( )