Remove renamed files
This commit is contained in:
parent
2109bdbc97
commit
bce8382d6e
|
@ -1,123 +0,0 @@
|
||||||
#!Python 3
|
|
||||||
import hashlib
|
|
||||||
import PySimpleGUI as SG
|
|
||||||
|
|
||||||
#########################################################################
|
|
||||||
# DisplayHash #
|
|
||||||
# A PySimpleGUI demo app that displays SHA1 hash for user browsed file #
|
|
||||||
# Useful and a recipe for GUI success #
|
|
||||||
#########################################################################
|
|
||||||
|
|
||||||
# ====____====____==== FUNCTION compute_hash_for_file(filename) ====____====____==== #
|
|
||||||
# Reads a file, computes the Hash #
|
|
||||||
# ---------------------------------------------------------------------------------- #
|
|
||||||
def compute_sha1_hash_for_file(filename):
|
|
||||||
try:
|
|
||||||
x = open(filename, "rb").read()
|
|
||||||
except:
|
|
||||||
return 0
|
|
||||||
|
|
||||||
m = hashlib.sha1()
|
|
||||||
m.update(x)
|
|
||||||
f_sha = m.hexdigest()
|
|
||||||
|
|
||||||
return f_sha
|
|
||||||
|
|
||||||
|
|
||||||
# ====____====____==== FUNCTION compute_hash_for_file(filename) ====____====____==== #
|
|
||||||
# Reads a file, computes the Hash #
|
|
||||||
# ---------------------------------------------------------------------------------- #
|
|
||||||
def compute_sha256_hash_for_file(filename):
|
|
||||||
try:
|
|
||||||
f = open(filename, "rb")
|
|
||||||
x = f.read()
|
|
||||||
except:
|
|
||||||
return 0
|
|
||||||
|
|
||||||
m = hashlib.sha256()
|
|
||||||
m.update(x)
|
|
||||||
f_sha = m.hexdigest()
|
|
||||||
|
|
||||||
return f_sha
|
|
||||||
|
|
||||||
|
|
||||||
# ====____====____==== Uses A GooeyGUI GUI ====____====____== #
|
|
||||||
# Get the filename, display the hash, dirt simple all around #
|
|
||||||
# ----------------------------------------------------------- #
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------- #
|
|
||||||
# Compute and display SHA1 hash #
|
|
||||||
# Builds and displays the form using the most basic building blocks #
|
|
||||||
# ---------------------------------------------------------------------- #
|
|
||||||
def HashManuallyBuiltGUI():
|
|
||||||
# ------- Form design ------- #
|
|
||||||
with SG.FlexForm('SHA-1 & 256 Hash', auto_size_text=True) as form:
|
|
||||||
form_rows = [[SG.Text('SHA-1 and SHA-256 Hashes for the file')],
|
|
||||||
[SG.InputText(), SG.FileBrowse()],
|
|
||||||
[SG.Submit(), SG.Cancel()]]
|
|
||||||
(button, (source_filename, )) = form.LayoutAndShow(form_rows)
|
|
||||||
|
|
||||||
if button == 'Submit':
|
|
||||||
if source_filename != '':
|
|
||||||
hash_sha1 = compute_sha1_hash_for_file(source_filename).upper()
|
|
||||||
hash_sha256 = compute_sha256_hash_for_file(source_filename).upper()
|
|
||||||
SG.MsgBox( 'Display A Hash in PySimpleGUI', 'The SHA-1 Hash for the file\n', source_filename, hash_sha1, 'SHA-256 is', hash_sha256, line_width=75)
|
|
||||||
else: SG.MsgBoxError('Display A Hash in PySimpleGUI', 'Illegal filename')
|
|
||||||
else:
|
|
||||||
SG.MsgBoxError('Display A Hash in PySimpleGUI', '* Cancelled *')
|
|
||||||
|
|
||||||
def HashManuallyBuiltGUINonContext():
|
|
||||||
# ------- Form design ------- #
|
|
||||||
form = SG.FlexForm('SHA-1 & 256 Hash', auto_size_text=True)
|
|
||||||
form_rows = [[SG.Text('SHA-1 and SHA-256 Hashes for the file')],
|
|
||||||
[SG.InputText(), SG.FileBrowse()],
|
|
||||||
[SG.Submit(), SG.Cancel()]]
|
|
||||||
(button, (source_filename, )) = form.LayoutAndShow(form_rows)
|
|
||||||
|
|
||||||
if button == 'Submit':
|
|
||||||
if source_filename != '':
|
|
||||||
hash_sha1 = compute_sha1_hash_for_file(source_filename).upper()
|
|
||||||
hash_sha256 = compute_sha256_hash_for_file(source_filename).upper()
|
|
||||||
SG.MsgBox( 'Display A Hash in PySimpleGUI', 'The SHA-1 Hash for the file\n', source_filename, hash_sha1, 'SHA-256 is', hash_sha256, line_width=75)
|
|
||||||
else: SG.MsgBoxError('Display A Hash in PySimpleGUI', 'Illegal filename')
|
|
||||||
else:
|
|
||||||
SG.MsgBoxError('Display A Hash in PySimpleGUI', '* Cancelled *')
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------- #
|
|
||||||
# Compute and display SHA1 hash #
|
|
||||||
# This one cheats and uses the higher-level Get A File pre-made func #
|
|
||||||
# Hey, it's a really common operation so why not? #
|
|
||||||
# ---------------------------------------------------------------------- #
|
|
||||||
def HashMostCompactGUI():
|
|
||||||
# ------- INPUT GUI portion ------- #
|
|
||||||
|
|
||||||
rc, source_filename = SG.GetFileBox('Display A Hash Using PySimpleGUI',
|
|
||||||
'Display a Hash code for file of your choice')
|
|
||||||
|
|
||||||
# ------- OUTPUT GUI results portion ------- #
|
|
||||||
if rc == True:
|
|
||||||
hash = compute_sha1_hash_for_file(source_filename)
|
|
||||||
SG.MsgBox('Display Hash - Compact GUI', 'The SHA-1 Hash for the file\n', source_filename, hash)
|
|
||||||
else:
|
|
||||||
SG.MsgBox('Display Hash - Compact GUI', '* Cancelled *')
|
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------------- #
|
|
||||||
# Our main calls two GUIs that act identically but use different calls #
|
|
||||||
# ---------------------------------------------------------------------- #
|
|
||||||
def main():
|
|
||||||
HashManuallyBuiltGUINonContext()
|
|
||||||
HashMostCompactGUI()
|
|
||||||
|
|
||||||
|
|
||||||
# ====____====____==== Pseudo-MAIN program ====____====____==== #
|
|
||||||
# This is our main-alike piece of code #
|
|
||||||
# + Starts up the GUI #
|
|
||||||
# + Gets values from GUI #
|
|
||||||
# + Runs DeDupe_folder based on GUI inputs #
|
|
||||||
# ------------------------------------------------------------- #
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
|
@ -1,56 +0,0 @@
|
||||||
import hashlib
|
|
||||||
import os
|
|
||||||
import PySimpleGUI as gg
|
|
||||||
|
|
||||||
|
|
||||||
# ====____====____==== FUNCTION DeDuplicate_folder(path) ====____====____==== #
|
|
||||||
# Function to de-duplicate the folder passed in #
|
|
||||||
# --------------------------------------------------------------------------- #
|
|
||||||
def FindDuplicatesFilesInFolder(path):
|
|
||||||
shatab = []
|
|
||||||
total = 0
|
|
||||||
small_count, dup_count, error_count = 0,0,0
|
|
||||||
pngdir = path
|
|
||||||
if not os.path.exists(path):
|
|
||||||
gg.MsgBox('Duplicate Finder', '** Folder doesn\'t exist***', path)
|
|
||||||
return
|
|
||||||
pngfiles = os.listdir(pngdir)
|
|
||||||
total_files = len(pngfiles)
|
|
||||||
for idx, f in enumerate(pngfiles):
|
|
||||||
if not gg.EasyProgressMeter('Counting Duplicates', idx+1, total_files, 'Counting Duplicate Files'):
|
|
||||||
break
|
|
||||||
total += 1
|
|
||||||
fname = os.path.join(pngdir, f)
|
|
||||||
if os.path.isdir(fname):
|
|
||||||
continue
|
|
||||||
x = open(fname, "rb").read()
|
|
||||||
|
|
||||||
m = hashlib.sha256()
|
|
||||||
m.update(x)
|
|
||||||
f_sha = m.digest()
|
|
||||||
if f_sha in shatab:
|
|
||||||
# uncomment next line to remove duplicate files
|
|
||||||
# os.remove(fname)
|
|
||||||
dup_count += 1
|
|
||||||
continue
|
|
||||||
shatab.append(f_sha)
|
|
||||||
|
|
||||||
msg = f'{total} Files processed\n'\
|
|
||||||
f'{dup_count} Duplicates found\n'
|
|
||||||
gg.MsgBox('Duplicate Finder Ended', msg)
|
|
||||||
|
|
||||||
# ====____====____==== Pseudo-MAIN program ====____====____==== #
|
|
||||||
# This is our main-alike piece of code #
|
|
||||||
# + Starts up the GUI #
|
|
||||||
# + Gets values from GUI #
|
|
||||||
# + Runs DeDupe_folder based on GUI inputs #
|
|
||||||
# ------------------------------------------------------------- #
|
|
||||||
if __name__ == '__main__':
|
|
||||||
|
|
||||||
source_folder = None
|
|
||||||
rc, source_folder = gg.GetPathBox('Duplicate Finder - Count number of duplicate files', 'Enter path to folder you wish to find duplicates in')
|
|
||||||
if rc is True and source_folder is not None:
|
|
||||||
FindDuplicatesFilesInFolder(source_folder)
|
|
||||||
else:
|
|
||||||
gg.MsgBoxCancel('Cancelling', '*** Cancelling ***')
|
|
||||||
exit(0)
|
|
|
@ -1,50 +0,0 @@
|
||||||
import PySimpleGUI as gg
|
|
||||||
import time
|
|
||||||
|
|
||||||
def main():
|
|
||||||
# ------- Make a new FlexForm ------- #
|
|
||||||
form = gg.FlexForm('GoodColors', auto_size_text=True, default_element_size=(30,2))
|
|
||||||
form.AddRow(gg.Text('Having trouble picking good colors? Try one of the colors defined by PySimpleGUI'))
|
|
||||||
form.AddRow(gg.Text('Here come the good colors as defined by PySimpleGUI'))
|
|
||||||
|
|
||||||
#===== Show some nice BLUE colors with yellow text ===== ===== ===== ===== ===== ===== =====#
|
|
||||||
text_color = gg.YELLOWS[0]
|
|
||||||
buttons = (gg.SimpleButton(f'BLUES[{j}]\n{c}', button_color=(text_color, c), size=(10,2)) for j, c in enumerate(gg.BLUES))
|
|
||||||
form.AddRow(gg.T('Button Colors Using PySimpleGUI.BLUES'))
|
|
||||||
form.AddRow(*buttons)
|
|
||||||
form.AddRow(gg.Text('_' * 100, size=(65, 1)))
|
|
||||||
|
|
||||||
#===== Show some nice PURPLE colors with yellow text ===== ===== ===== ===== ===== ===== =====#
|
|
||||||
buttons = (gg.SimpleButton(f'PURPLES[{j}]\n{c}', button_color=(text_color, c), size=(10,2)) for j, c in enumerate(gg.PURPLES))
|
|
||||||
form.AddRow(gg.T('Button Colors Using PySimpleGUI.PURPLES'))
|
|
||||||
form.AddRow(*buttons)
|
|
||||||
form.AddRow(gg.Text('_' * 100, size=(65, 1)))
|
|
||||||
|
|
||||||
#===== Show some nice GREEN colors with yellow text ===== ===== ===== ===== ===== ===== =====#
|
|
||||||
buttons = (gg.SimpleButton(f'GREENS[{j}]\n{c}', button_color=(text_color, c), size=(10,2)) for j, c in enumerate(gg.GREENS))
|
|
||||||
form.AddRow(gg.T('Button Colors Using PySimpleGUI.GREENS'))
|
|
||||||
form.AddRow(*buttons)
|
|
||||||
form.AddRow(gg.Text('_' * 100, size=(65, 1)))
|
|
||||||
|
|
||||||
#===== Show some nice TAN colors with yellow text ===== ===== ===== ===== ===== ===== =====#
|
|
||||||
text_color = gg.GREENS[0] # let's use GREEN text on the tan
|
|
||||||
buttons = (gg.SimpleButton(f'TANS[{j}]\n{c}', button_color=(text_color, c), size=(10,2)) for j, c in enumerate(gg.TANS))
|
|
||||||
form.AddRow(gg.T('Button Colors Using PySimpleGUI.TANS'))
|
|
||||||
form.AddRow(*buttons)
|
|
||||||
form.AddRow(gg.Text('_' * 100, size=(65, 1)))
|
|
||||||
|
|
||||||
#===== Show some nice YELLOWS colors with black text ===== ===== ===== ===== ===== ===== =====#
|
|
||||||
text_color = 'black' # let's use black text on the tan
|
|
||||||
buttons = (gg.SimpleButton(f'YELLOWS[{j}]\n{c}', button_color=(text_color, c), size=(10,2)) for j, c in enumerate(gg.YELLOWS))
|
|
||||||
form.AddRow(gg.T('Button Colors Using PySimpleGUI.YELLOWS'))
|
|
||||||
form.AddRow(*buttons)
|
|
||||||
form.AddRow(gg.Text('_' * 100, size=(65, 1)))
|
|
||||||
|
|
||||||
|
|
||||||
#===== Add a click me button for fun and SHOW the form ===== ===== ===== ===== ===== ===== =====#
|
|
||||||
form.AddRow(gg.SimpleButton('Click ME!'))
|
|
||||||
(button, value) = form.Show() # show it!
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
|
@ -1,54 +0,0 @@
|
||||||
import PySimpleGUI as SG
|
|
||||||
import subprocess
|
|
||||||
import howdoi
|
|
||||||
|
|
||||||
# Test this command in a dos window if you are having trouble.
|
|
||||||
HOW_DO_I_COMMAND = 'python -m howdoi.howdoi'
|
|
||||||
|
|
||||||
# if you want an icon on your taskbar for this gui, then change this line of code to point to the ICO file
|
|
||||||
DEFAULT_ICON = 'E:\\TheRealMyDocs\\Icons\\QuestionMark.ico'
|
|
||||||
|
|
||||||
def HowDoI():
|
|
||||||
'''
|
|
||||||
Make and show a window (PySimpleGUI form) that takes user input and sends to the HowDoI web oracle
|
|
||||||
Excellent example of 2 GUI concepts
|
|
||||||
1. Output Element that will show text in a scrolled window
|
|
||||||
2. Non-Window-Closing Buttons - These buttons will cause the form to return with the form's values, but doesn't close the form
|
|
||||||
:return: never returns
|
|
||||||
'''
|
|
||||||
# ------- Make a new FlexForm ------- #
|
|
||||||
form = SG.FlexForm('How Do I ??', auto_size_text=True, default_element_size=(30, 2), icon=DEFAULT_ICON)
|
|
||||||
form.AddRow(SG.Text('Ask and your answer will appear here....', size=(40, 1)))
|
|
||||||
form.AddRow(SG.Output(size=(90, 20)))
|
|
||||||
form.AddRow(SG.Multiline(size=(85, 5), enter_submits=True),
|
|
||||||
SG.ReadFormButton('SEND', button_color=(SG.YELLOWS[0], SG.BLUES[0])),
|
|
||||||
SG.SimpleButton('EXIT', button_color=(SG.YELLOWS[0], SG.GREENS[0])))
|
|
||||||
|
|
||||||
# ---===--- Loop taking in user input and using it to query HowDoI --- #
|
|
||||||
while True:
|
|
||||||
(button, value) = form.Read()
|
|
||||||
if button == 'SEND':
|
|
||||||
QueryHowDoI(value[0][:-1]) # send string without carriage return on end
|
|
||||||
else:
|
|
||||||
break # exit button clicked
|
|
||||||
|
|
||||||
exit(69)
|
|
||||||
|
|
||||||
def QueryHowDoI(Query):
|
|
||||||
'''
|
|
||||||
Kicks off a subprocess to send the 'Query' to HowDoI
|
|
||||||
Prints the result, which in this program will route to a gooeyGUI window
|
|
||||||
:param Query: text english question to ask the HowDoI web engine
|
|
||||||
:return: nothing
|
|
||||||
'''
|
|
||||||
howdoi_command = HOW_DO_I_COMMAND
|
|
||||||
t = subprocess.Popen(howdoi_command + ' '+ Query, stdout=subprocess.PIPE)
|
|
||||||
(output, err) = t.communicate()
|
|
||||||
print('You asked: '+ Query)
|
|
||||||
print('_______________________________________')
|
|
||||||
print(output.decode("utf-8") )
|
|
||||||
exit_code = t.wait()
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
HowDoI()
|
|
||||||
|
|
|
@ -1,60 +0,0 @@
|
||||||
import PySimpleGUI as sg
|
|
||||||
|
|
||||||
#
|
|
||||||
# An Async Demonstration of a media player
|
|
||||||
# Uses button images for a super snazzy look
|
|
||||||
# See how it looks here:
|
|
||||||
# https://user-images.githubusercontent.com/13696193/43159403-45c9726e-8f50-11e8-9da0-0d272e20c579.jpg
|
|
||||||
#
|
|
||||||
|
|
||||||
|
|
||||||
def MediaPlayerGUI():
|
|
||||||
|
|
||||||
# Images are located in a subfolder in the Demo Media Player.py folder
|
|
||||||
image_pause = './ButtonGraphics/Pause.png'
|
|
||||||
image_restart = './ButtonGraphics/Restart.png'
|
|
||||||
image_next = './ButtonGraphics/Next.png'
|
|
||||||
image_exit = './ButtonGraphics/Exit.png'
|
|
||||||
|
|
||||||
# A text element that will be changed to display messages in the GUI
|
|
||||||
TextElem = sg.Text('', size=(20, 3), font=("Helvetica", 14))
|
|
||||||
|
|
||||||
# Open a form, note that context manager can't be used generally speaking for async forms
|
|
||||||
form = sg.FlexForm('Media File Player', auto_size_text=True, default_element_size=(20, 1),
|
|
||||||
font=("Helvetica", 25))
|
|
||||||
# define layout of the rows
|
|
||||||
layout= [[sg.Text('Media File Player', size=(20, 1), font=("Helvetica", 25))],
|
|
||||||
[TextElem],
|
|
||||||
[sg.ReadFormButton('Restart Song', button_color=sg.TRANSPARENT_BUTTON,
|
|
||||||
image_filename=image_restart, image_size=(50, 50), image_subsample=2, border_width=0,
|
|
||||||
size=(10, 2), font=("Helvetica", 15)), sg.Text(' ' * 2),
|
|
||||||
sg.ReadFormButton('Pause', button_color=sg.TRANSPARENT_BUTTON,
|
|
||||||
image_filename=image_pause, image_size=(50, 50), image_subsample=2, border_width=0,
|
|
||||||
font=("Helvetica", 15), size=(10, 2)), sg.Text(' ' * 2),
|
|
||||||
sg.ReadFormButton('Next', button_color=sg.TRANSPARENT_BUTTON,
|
|
||||||
image_filename=image_next, image_size=(50, 50), image_subsample=2, border_width=0,
|
|
||||||
size=(10, 2), font=("Helvetica", 15)), sg.Text(' ' * 2),
|
|
||||||
sg.Text(' ' * 2), sg.SimpleButton('Exit', button_color=sg.TRANSPARENT_BUTTON,
|
|
||||||
image_filename=image_exit, image_size=(50, 50), image_subsample=2, border_width=0,
|
|
||||||
size=(10, 2), font=("Helvetica", 15))],
|
|
||||||
[sg.Text('Treble', font=("Helvetica", 15), size=(6, 1)),
|
|
||||||
sg.Slider(range=(-10, 10), default_value=0, size=(10, 20), orientation='vertical', font=("Helvetica", 15)),
|
|
||||||
sg.Text(' ' * 5),
|
|
||||||
sg.Text('Volume', font=("Helvetica", 15), size=(7, 1)),
|
|
||||||
sg.Slider(range=(-10, 10), default_value=0, size=(10, 20), orientation='vertical', font=("Helvetica", 15))],
|
|
||||||
]
|
|
||||||
|
|
||||||
# Call the same LayoutAndRead but indicate the form is non-blocking
|
|
||||||
form.LayoutAndRead(layout, non_blocking=True)
|
|
||||||
# Our event loop
|
|
||||||
while(True):
|
|
||||||
# Read the form (this call will not block)
|
|
||||||
button, values = form.ReadNonBlocking()
|
|
||||||
if button == 'Exit':
|
|
||||||
break
|
|
||||||
# If a button was pressed, display it on the GUI by updating the text element
|
|
||||||
if button:
|
|
||||||
TextElem.Update(button)
|
|
||||||
|
|
||||||
MediaPlayerGUI()
|
|
||||||
|
|
|
@ -1,59 +0,0 @@
|
||||||
import PySimpleGUI as sg
|
|
||||||
import time
|
|
||||||
|
|
||||||
def main():
|
|
||||||
StatusOutputExample()
|
|
||||||
|
|
||||||
# form that doen't block
|
|
||||||
def StatusOutputExample_context_manager():
|
|
||||||
with sg.FlexForm('Running Timer', auto_size_text=True) as form:
|
|
||||||
output_element = sg.Text('', size=(8, 2), font=('Helvetica', 20))
|
|
||||||
form_rows = [[sg.Text('Non-blocking GUI with updates')],
|
|
||||||
[output_element],
|
|
||||||
[sg.SimpleButton('Quit')]]
|
|
||||||
|
|
||||||
form.LayoutAndRead(form_rows, non_blocking=True)
|
|
||||||
|
|
||||||
for i in range(1, 1000):
|
|
||||||
output_element.Update('{:02d}:{:02d}.{:02d}'.format(*divmod(int(i/100), 60), i%100))
|
|
||||||
button, values = form.ReadNonBlocking()
|
|
||||||
if values is None or button == 'Quit':
|
|
||||||
break
|
|
||||||
time.sleep(.01)
|
|
||||||
else:
|
|
||||||
form.CloseNonBlockingForm()
|
|
||||||
|
|
||||||
|
|
||||||
# form that doen't block
|
|
||||||
def StatusOutputExample():
|
|
||||||
# Make a form, but don't use context manager
|
|
||||||
form = sg.FlexForm('Running Timer', auto_size_text=True)
|
|
||||||
# Create a text element that will be updated with status information on the GUI itself
|
|
||||||
output_element = sg.Text('', size=(8, 2), font=('Helvetica', 20))
|
|
||||||
# Create the rows
|
|
||||||
form_rows = [[sg.Text('Non-blocking GUI with updates')],
|
|
||||||
[output_element],
|
|
||||||
[sg.SimpleButton('Quit')]]
|
|
||||||
# Layout the rows of the form and perform a read. Indicate the form is non-blocking!
|
|
||||||
form.LayoutAndRead(form_rows, non_blocking=True)
|
|
||||||
|
|
||||||
#
|
|
||||||
# Some place later in your code...
|
|
||||||
# You need to perform a ReadNonBlocking on your form every now and then or
|
|
||||||
# else it won't refresh
|
|
||||||
#
|
|
||||||
|
|
||||||
for i in range(1, 1000):
|
|
||||||
output_element.Update('{:02d}:{:02d}.{:02d}'.format(*divmod(int(i / 100), 60), i % 100))
|
|
||||||
button, values = form.ReadNonBlocking()
|
|
||||||
if values is None or button == 'Quit':
|
|
||||||
break
|
|
||||||
time.sleep(.01)
|
|
||||||
else:
|
|
||||||
form.CloseNonBlockingForm()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
|
|
||||||
main()
|
|
167
Demo Recipes.py
167
Demo Recipes.py
|
@ -1,167 +0,0 @@
|
||||||
import time
|
|
||||||
from random import randint
|
|
||||||
import PySimpleGUI as sg
|
|
||||||
|
|
||||||
# A simple blocking form. Your best starter-form
|
|
||||||
def SourceDestFolders():
|
|
||||||
with sg.FlexForm('Demo Source / Destination Folders', auto_size_text=True) as form:
|
|
||||||
form_rows = [[sg.Text('Enter the Source and Destination folders')],
|
|
||||||
[sg.Text('Source Folder', size=(15, 1), auto_size_text=False, justification='right'), sg.InputText('Source')],
|
|
||||||
[sg.Text('Destination Folder', size=(15, 1), auto_size_text=False, justification='right'), sg.InputText('Dest'), sg.FolderBrowse()],
|
|
||||||
[sg.Submit(), sg.Cancel()]]
|
|
||||||
|
|
||||||
button, (source, dest) = form.LayoutAndRead(form_rows)
|
|
||||||
if button == 'Submit':
|
|
||||||
sg.MsgBox('Submitted', 'The user entered source:', source, 'Destination folder:', dest, 'Using button', button)
|
|
||||||
else:
|
|
||||||
sg.MsgBoxError('Cancelled', 'User Cancelled')
|
|
||||||
|
|
||||||
# YOUR BEST STARTING POINT
|
|
||||||
# This is a form showing you all of the basic Elements (widgets)
|
|
||||||
# Some have a few of the optional parameters set, but there are more to choose from
|
|
||||||
# You want to use the context manager because it will free up resources when you are finished
|
|
||||||
# Use this especially if you are runningm multi-threaded
|
|
||||||
# Where you free up resources is really important to tkinter
|
|
||||||
def Everything():
|
|
||||||
with sg.FlexForm('Everything bagel', auto_size_text=True, default_element_size=(40, 1)) as form:
|
|
||||||
layout = [
|
|
||||||
[sg.Text('All graphic widgets in one form!', size=(30, 1), font=("Helvetica", 25), text_color='blue')],
|
|
||||||
[sg.Text('Here is some text.... and a place to enter text')],
|
|
||||||
[sg.InputText()],
|
|
||||||
[sg.Checkbox('My first checkbox!'), sg.Checkbox('My second checkbox!', default=True)],
|
|
||||||
[sg.Radio('My first Radio! ', "RADIO1", default=True), sg.Radio('My second Radio!', "RADIO1")],
|
|
||||||
[sg.Multiline(default_text='This is the default Text shoulsd you decide not to type anything',
|
|
||||||
scale=(2, 10))],
|
|
||||||
[sg.InputCombo(['Combobox 1', 'Combobox 2'], size=(20, 3)),
|
|
||||||
sg.Slider(range=(1, 100), orientation='h', size=(35, 20), default_value=85)],
|
|
||||||
[sg.Listbox(values=['Listbox 1', 'Listbox 2', 'Listbox 3'], size=(30, 6)),
|
|
||||||
sg.Slider(range=(1, 100), orientation='v', size=(10, 20), default_value=25),
|
|
||||||
sg.Slider(range=(1, 100), orientation='v', size=(10, 20), default_value=75),
|
|
||||||
sg.Slider(range=(1, 100), orientation='v', size=(10, 20), default_value=10)],
|
|
||||||
[sg.Text('_' * 100, size=(70, 1))],
|
|
||||||
[sg.Text('Choose Source and Destination Folders', size=(35, 1))],
|
|
||||||
[sg.Text('Source Folder', size=(15, 1), auto_size_text=False, justification='right'), sg.InputText('Source'), sg.FolderBrowse()],
|
|
||||||
[sg.Text('Destination Folder', size=(15, 1), auto_size_text=False, justification='right'), sg.InputText('Dest'),
|
|
||||||
sg.FolderBrowse()],
|
|
||||||
[sg.Submit(), sg.Cancel(), sg.SimpleButton('Customized', button_color=('white', 'green'))]
|
|
||||||
]
|
|
||||||
|
|
||||||
button, values = form.LayoutAndRead(layout)
|
|
||||||
|
|
||||||
sg.MsgBox('Title', 'Typical message box', 'The results of the form are a lot of data! Get ready... ', 'The button clicked was "{}"'.format(button), 'The values are', values)
|
|
||||||
|
|
||||||
# Should you decide not to use a context manager, then try this form as your starting point
|
|
||||||
# Be aware that tkinter, which this is based on, is picky about who frees up resources, especially if
|
|
||||||
# you are running multithreaded
|
|
||||||
def Everything_NoContextManager():
|
|
||||||
form = sg.FlexForm('Everything bagel', auto_size_text=True, default_element_size=(40, 1))
|
|
||||||
layout = [[sg.Text('All graphic widgets in one form!', size=(30, 1), font=("Helvetica", 25), text_color='blue')],
|
|
||||||
[sg.Text('Here is some text.... and a place to enter text')],
|
|
||||||
[sg.InputText()],
|
|
||||||
[sg.Checkbox('My first checkbox!'), sg.Checkbox('My second checkbox!', default=True)],
|
|
||||||
[sg.Radio('My first Radio! ', "RADIO1", default=True), sg.Radio('My second Radio!', "RADIO1")],
|
|
||||||
[sg.Multiline(default_text='This is the default Text shoulsd you decide not to type anything', scale=(2, 10))],
|
|
||||||
[sg.InputCombo(['Combobox 1', 'Combobox 2'], size=(20, 3)), sg.Slider(range=(1, 100), orientation='h', size=(35, 20), default_value=85)],
|
|
||||||
[sg.Listbox(values=['Listbox 1', 'Listbox 2', 'Listbox 3'], size=(30, 6)),
|
|
||||||
sg.Slider(range=(1, 100), orientation='v', size=(10, 20), default_value=25),
|
|
||||||
sg.Slider(range=(1, 100), orientation='v', size=(10, 20), default_value=75),
|
|
||||||
sg.Slider(range=(1, 100), orientation='v', size=(10, 20), default_value=10)],
|
|
||||||
[sg.Text('_' * 100, size=(70, 1))],
|
|
||||||
[sg.Text('Choose Source and Destination Folders', size=(35, 1), text_color='red')],
|
|
||||||
[sg.Text('Source Folder', size=(15, 1), auto_size_text=False, justification='right'), sg.InputText('Source'), sg.FolderBrowse()],
|
|
||||||
[sg.Text('Destination Folder', size=(15, 1), auto_size_text=False, justification='right'), sg.InputText('Dest'), sg.FolderBrowse()],
|
|
||||||
[sg.Submit(), sg.Cancel(), sg.SimpleButton('Customized', button_color=('white', 'green'))]]
|
|
||||||
|
|
||||||
button, values = form.LayoutAndRead(layout)
|
|
||||||
del(form)
|
|
||||||
|
|
||||||
sg.MsgBox('Title', 'Typical message box', 'Here are the restults! There is one entry per input field ', 'The button clicked was "{}"'.format(button), 'The values are', values)
|
|
||||||
|
|
||||||
def ProgressMeter():
|
|
||||||
for i in range(1,10000):
|
|
||||||
if not sg.EasyProgressMeter('My Meter', i + 1, 10000): break
|
|
||||||
# SG.Print(i)
|
|
||||||
|
|
||||||
# Blocking form that doesn't close
|
|
||||||
def ChatBot():
|
|
||||||
with sg.FlexForm('Chat Window', auto_size_text=True, default_element_size=(30, 2)) as form:
|
|
||||||
layout = [[(sg.Text('This is where standard out is being routed', size=[40, 1]))],
|
|
||||||
[sg.Output(size=(80, 20))],
|
|
||||||
[sg.Multiline(size=(70, 5), enter_submits=True), sg.ReadFormButton('SEND', button_color=(sg.YELLOWS[0], sg.BLUES[0])), sg.SimpleButton('EXIT', button_color=(sg.YELLOWS[0], sg.GREENS[0]))]]
|
|
||||||
# notice this is NOT the usual LayoutAndRead call because you don't yet want to read the form
|
|
||||||
# if you call LayoutAndRead from here, then you will miss the first button click
|
|
||||||
form.Layout(layout)
|
|
||||||
# ---===--- Loop taking in user input and using it to query HowDoI web oracle --- #
|
|
||||||
while True:
|
|
||||||
button, value = form.Read()
|
|
||||||
if button == 'SEND':
|
|
||||||
print(value)
|
|
||||||
else:
|
|
||||||
break
|
|
||||||
|
|
||||||
# Shows a form that's a running counter
|
|
||||||
# this is the basic design pattern if you can keep your reading of the
|
|
||||||
# form within the 'with' block. If your read occurs far away in your code from the form creation
|
|
||||||
# then you will want to use the NonBlockingPeriodicUpdateForm example
|
|
||||||
def NonBlockingPeriodicUpdateForm_ContextManager():
|
|
||||||
with sg.FlexForm('Running Timer', auto_size_text=True) as form:
|
|
||||||
text_element = sg.Text('', size=(10, 2), font=('Helvetica', 20), text_color='red', justification='center')
|
|
||||||
layout = [[sg.Text('Non blocking GUI with updates', justification='center')],
|
|
||||||
[text_element],
|
|
||||||
[sg.T(' ' * 15), sg.Quit()]]
|
|
||||||
form.LayoutAndRead(layout, non_blocking=True)
|
|
||||||
|
|
||||||
for i in range(1,500):
|
|
||||||
text_element.Update('{:02d}:{:02d}.{:02d}'.format((i // 100) // 60, (i // 100) % 60, i % 100))
|
|
||||||
button, values = form.ReadNonBlocking()
|
|
||||||
if values is None or button == 'Quit': # if user closed the window using X
|
|
||||||
break
|
|
||||||
time.sleep(.01)
|
|
||||||
else:
|
|
||||||
# if the loop finished then need to close the form for the user
|
|
||||||
form.CloseNonBlockingForm()
|
|
||||||
|
|
||||||
# Use this context-manager-free version if your read of the form occurs far away in your code
|
|
||||||
# from the form creation (call to LayoutAndRead)
|
|
||||||
def NonBlockingPeriodicUpdateForm():
|
|
||||||
# Show a form that's a running counter
|
|
||||||
form = sg.FlexForm('Running Timer', auto_size_text=True)
|
|
||||||
text_element = sg.Text('', size=(10, 2), font=('Helvetica', 20), justification='center')
|
|
||||||
form_rows = [[sg.Text('Non blocking GUI with updates')],
|
|
||||||
[text_element],
|
|
||||||
[sg.T(' ' * 15), sg.Quit()]]
|
|
||||||
form.LayoutAndRead(form_rows, non_blocking=True)
|
|
||||||
|
|
||||||
for i in range(1,50000):
|
|
||||||
text_element.Update('{:02d}:{:02d}.{:02d}'.format((i//100)//60, (i//100)%60, i%100))
|
|
||||||
button, values = form.ReadNonBlocking()
|
|
||||||
if values is None or button == 'Quit': # if user closed the window using X or clicked Quit button
|
|
||||||
break
|
|
||||||
time.sleep(.01)
|
|
||||||
else:
|
|
||||||
# if the loop finished then need to close the form for the user
|
|
||||||
form.CloseNonBlockingForm()
|
|
||||||
del(form)
|
|
||||||
|
|
||||||
def DebugTest():
|
|
||||||
# SG.Print('How about we print a bunch of random numbers?', , size=(90,40))
|
|
||||||
for i in range (1,300):
|
|
||||||
sg.Print(i, randint(1, 1000), end='', sep='-')
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
|
||||||
# SG.SetOptions(border_width=1, font=("Helvetica", 10), button_color=('white', SG.BLUES[0]), slider_border_width=1)
|
|
||||||
NonBlockingPeriodicUpdateForm_ContextManager()
|
|
||||||
NonBlockingPeriodicUpdateForm()
|
|
||||||
Everything_NoContextManager()
|
|
||||||
Everything()
|
|
||||||
ChatBot()
|
|
||||||
ProgressMeter()
|
|
||||||
SourceDestFolders()
|
|
||||||
ChatBot()
|
|
||||||
DebugTest()
|
|
||||||
sg.MsgBox('Done with all recipes')
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
||||||
exit(69)
|
|
|
@ -1,89 +0,0 @@
|
||||||
import PySimpleGUI as sg
|
|
||||||
|
|
||||||
MAX_NUMBER_OF_THREADS = 12
|
|
||||||
|
|
||||||
def eBaySuperSearcherGUI():
|
|
||||||
# Drop Down list of options
|
|
||||||
configs = ('0 - Gruen - Started 2 days ago in Watches',
|
|
||||||
'1 - Gruen - Currently Active in Watches',
|
|
||||||
'2 - Alpina - Currently Active in Jewelry',
|
|
||||||
'3 - Gruen - Ends in 1 day in Watches',
|
|
||||||
'4 - Gruen - Completed in Watches',
|
|
||||||
'5 - Gruen - Advertising',
|
|
||||||
'6 - Gruen - Currently Active in Jewelry',
|
|
||||||
'7 - Gruen - Price Test',
|
|
||||||
'8 - Gruen - No brand name specified')
|
|
||||||
|
|
||||||
us_categories = ('Use Default with no change',
|
|
||||||
'All - 1',
|
|
||||||
'Jewelry - 281',
|
|
||||||
' Watches - 14324',
|
|
||||||
' Wristwatches - 31387',
|
|
||||||
' Pocket Watches - 3937',
|
|
||||||
'Advertising - 34',
|
|
||||||
' Watch Ads - 165254'
|
|
||||||
)
|
|
||||||
|
|
||||||
german_categories =('Use Default with no change',
|
|
||||||
'All - 1',
|
|
||||||
'Jewelry - 281',
|
|
||||||
' Watches - 14324',
|
|
||||||
' Wristwatches - 31387',
|
|
||||||
' Pocket Watches - 3937',
|
|
||||||
'Advertising - 1',
|
|
||||||
' Watch Ads - 19823'
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
# the form layout
|
|
||||||
with sg.FlexForm('EBay Super Searcher', auto_size_text=True) as form:
|
|
||||||
with sg.FlexForm('EBay Super Searcher') as form2:
|
|
||||||
layout_tab_1 = [[sg.Text('eBay Super Searcher!', size=(60,1), font=('helvetica', 15))],
|
|
||||||
[sg.Text('Choose base configuration to run')],
|
|
||||||
[sg.InputCombo(configs)],
|
|
||||||
[sg.Text('_'*100, size=(80,1))],
|
|
||||||
[sg.InputText(),sg.Text('Choose Destination Folder'), sg.FolderBrowse(target=(sg.ThisRow,0))],
|
|
||||||
[sg.InputText(),sg.Text('Custom text to add to folder name')],
|
|
||||||
[sg.Text('_'*100, size=(80,1))],
|
|
||||||
[sg.Checkbox('US', default=True, size=(15, 1)), sg.Checkbox('German', size=(15, 1), default=True, )],
|
|
||||||
[sg.Radio('Active Listings','ActiveComplete', default = True,size=(15, 1)), sg.Radio('Completed Listings', 'ActiveComplete', size=(15, 1))],
|
|
||||||
[sg.Text('_'*100, size=(80,1))],
|
|
||||||
[sg.Checkbox('Save Images', size=(15,1)),sg.Checkbox('Save PDFs', size=(15,1)), sg.Checkbox('Extract PDFs', size=(15,1))],
|
|
||||||
[sg.Text('_'*100, size=(80,1))],
|
|
||||||
[sg.Text('Time Filters')],
|
|
||||||
[sg.Radio('No change','time', default=True),sg.Radio('ALL listings','time'),sg.Radio('Started 1 day ago','time', size=(15,1)),sg.Radio('Started 2 days ago','time', size=(15,1)), sg.Radio('Ends in 1 day','time', size=(15,1))],
|
|
||||||
[sg.Text('_'*100, size=(80,1))],
|
|
||||||
[sg.Text('Price Range'), sg.InputText(size=(10,1)),sg.Text('To'), sg.InputText(size=(10,1))],
|
|
||||||
[sg.Text('_'*100, size=(80,1))],
|
|
||||||
[sg.Submit(button_color=('red', 'yellow')), sg.Cancel(button_color=('white', 'blue')), sg.Text(f'{MAX_NUMBER_OF_THREADS} Threads will be started')]]
|
|
||||||
|
|
||||||
|
|
||||||
# First category is default (need to special case this)
|
|
||||||
layout_tab_2 = [[sg.Text('Choose Category')],
|
|
||||||
[sg.Text('US Categories'),sg.Text('German Categories')],
|
|
||||||
[sg.Radio(us_categories[0],'CATUS', default=True), sg.Radio(german_categories[0], 'CATDE', default=True)]]
|
|
||||||
|
|
||||||
for i,cat in enumerate(us_categories):
|
|
||||||
if i == 0: continue # skip first one
|
|
||||||
layout_tab_2.append([sg.Radio(cat,'CATUS'), sg.Radio(german_categories[i],'CATDE')])
|
|
||||||
|
|
||||||
|
|
||||||
layout_tab_2.append([sg.Text('_' * 100, size=(75, 1))])
|
|
||||||
layout_tab_2.append([sg.Text('US Search String Override')])
|
|
||||||
layout_tab_2.append([sg.InputText(size=(100,1))])
|
|
||||||
layout_tab_2.append([sg.Text('German Search String Override')])
|
|
||||||
layout_tab_2.append([sg.InputText(size=(100,1))])
|
|
||||||
layout_tab_2.append([sg.Text('Typical US Search String')])
|
|
||||||
layout_tab_2.append([sg.InputText(size=(100,1), default_text='gruen -sara -quarz -quartz -embassy -bob -robert -elephants -adidas -LED ')])
|
|
||||||
layout_tab_2.append([sg.Text('_' * 100, size=(75, 1))])
|
|
||||||
layout_tab_2.append([sg.Submit(button_color=('red', 'yellow'),auto_size_text=True), sg.Cancel(button_color=('white', 'blue'), auto_size_text=True)])
|
|
||||||
|
|
||||||
results =sg.ShowTabbedForm('eBay Super Searcher', (form,layout_tab_1,'Where To Save'), (form2, layout_tab_2, 'Categories & Search String'))
|
|
||||||
|
|
||||||
return results
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
results = eBaySuperSearcherGUI()
|
|
||||||
print(results)
|
|
||||||
sg.MsgBox('Results', results)
|
|
Loading…
Reference in New Issue