Merge pull request #4420 from PySimpleGUI/Dev-latest
New popup - popup_error_with_traceback. Better line length handling i…
This commit is contained in:
commit
320987f379
|
@ -1,6 +1,6 @@
|
||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
|
|
||||||
version = __version__ = "4.44.0.1 Unreleased\nWindow.current_location docstring update to indicate value my be off due to titlebar."
|
version = __version__ = "4.44.0.2 Unreleased\nWindow.current_location docstring update to indicate value my be off due to titlebar, Menu element fixed problem of updates modifying the original menu spec, better string length handling in error popups, New popup function - popup_error_with_traceback allows you to show error info with a button to take the user to the line with the problem"
|
||||||
|
|
||||||
__version__ = version.split()[0] # For PEP 396 and PEP 345
|
__version__ = version.split()[0] # For PEP 396 and PEP 345
|
||||||
|
|
||||||
|
@ -115,6 +115,7 @@ import textwrap
|
||||||
import inspect
|
import inspect
|
||||||
import traceback
|
import traceback
|
||||||
import difflib
|
import difflib
|
||||||
|
import copy
|
||||||
|
|
||||||
try: # Because Raspberry Pi is still on 3.4....it's not critical if this module isn't imported on the Pi
|
try: # Because Raspberry Pi is still on 3.4....it's not critical if this module isn't imported on the Pi
|
||||||
from typing import List, Any, Union, Tuple, Dict, SupportsAbs, Optional # because this code has to run on 2.7 can't use real type hints. Must do typing only in comments
|
from typing import List, Any, Union, Tuple, Dict, SupportsAbs, Optional # because this code has to run on 2.7 can't use real type hints. Must do typing only in comments
|
||||||
|
@ -6958,8 +6959,9 @@ class Menu(Element):
|
||||||
|
|
||||||
self.BackgroundColor = background_color if background_color is not None else theme_input_background_color()
|
self.BackgroundColor = background_color if background_color is not None else theme_input_background_color()
|
||||||
self.TextColor = text_color if text_color is not None else theme_input_text_color()
|
self.TextColor = text_color if text_color is not None else theme_input_text_color()
|
||||||
|
|
||||||
self.DisabledTextColor = disabled_text_color if disabled_text_color is not None else COLOR_SYSTEM_DEFAULT
|
self.DisabledTextColor = disabled_text_color if disabled_text_color is not None else COLOR_SYSTEM_DEFAULT
|
||||||
self.MenuDefinition = menu_definition
|
self.MenuDefinition = copy.deepcopy(menu_definition)
|
||||||
self.Widget = self.TKMenu = None # type: tk.Menu
|
self.Widget = self.TKMenu = None # type: tk.Menu
|
||||||
self.MenuItemChosen = None
|
self.MenuItemChosen = None
|
||||||
key = key if key is not None else k
|
key = key if key is not None else k
|
||||||
|
@ -7001,10 +7003,10 @@ class Menu(Element):
|
||||||
return
|
return
|
||||||
|
|
||||||
if menu_definition is not None:
|
if menu_definition is not None:
|
||||||
self.MenuDefinition = menu_definition
|
self.MenuDefinition = copy.deepcopy(menu_definition)
|
||||||
self.TKMenu = tk.Menu(self.ParentForm.TKroot, tearoff=self.Tearoff) # create the menubar
|
self.TKMenu = tk.Menu(self.ParentForm.TKroot, tearoff=self.Tearoff) # create the menubar
|
||||||
menubar = self.TKMenu
|
menubar = self.TKMenu
|
||||||
for menu_entry in menu_definition:
|
for menu_entry in self.MenuDefinition:
|
||||||
baritem = tk.Menu(menubar, tearoff=self.Tearoff)
|
baritem = tk.Menu(menubar, tearoff=self.Tearoff)
|
||||||
if self.Font is not None:
|
if self.Font is not None:
|
||||||
baritem.config(font=self.Font)
|
baritem.config(font=self.Font)
|
||||||
|
@ -7022,7 +7024,7 @@ class Menu(Element):
|
||||||
if len(menu_entry) > 1:
|
if len(menu_entry) > 1:
|
||||||
AddMenuItem(baritem, menu_entry[1], self)
|
AddMenuItem(baritem, menu_entry[1], self)
|
||||||
|
|
||||||
if visible == False:
|
if visible is False:
|
||||||
self.ParentForm.TKroot.configure(menu=[]) # this will cause the menubar to disappear
|
self.ParentForm.TKroot.configure(menu=[]) # this will cause the menubar to disappear
|
||||||
elif self.TKMenu is not None:
|
elif self.TKMenu is not None:
|
||||||
self.ParentForm.TKroot.configure(menu=self.TKMenu)
|
self.ParentForm.TKroot.configure(menu=self.TKMenu)
|
||||||
|
@ -12177,12 +12179,12 @@ def AddMenuItem(top_menu, sub_menu_info, element, is_sub_menu=False, skip=False,
|
||||||
underline=pos, state='disabled')
|
underline=pos, state='disabled')
|
||||||
else:
|
else:
|
||||||
top_menu.add_cascade(label=sub_menu_info[i], menu=new_menu, underline=pos)
|
top_menu.add_cascade(label=sub_menu_info[i], menu=new_menu, underline=pos)
|
||||||
AddMenuItem(new_menu, sub_menu_info[i + 1], element, is_sub_menu=True)
|
AddMenuItem(new_menu, sub_menu_info[i + 1], element, is_sub_menu=True, right_click_menu=right_click_menu)
|
||||||
i += 1 # skip the next one
|
i += 1 # skip the next one
|
||||||
else:
|
else:
|
||||||
AddMenuItem(top_menu, item, element)
|
AddMenuItem(top_menu, item, element, right_click_menu=right_click_menu)
|
||||||
else:
|
else:
|
||||||
AddMenuItem(top_menu, item, element)
|
AddMenuItem(top_menu, item, element, right_click_menu=right_click_menu)
|
||||||
i += 1
|
i += 1
|
||||||
return return_val
|
return return_val
|
||||||
|
|
||||||
|
@ -12648,7 +12650,7 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
|
||||||
tkbutton.bind('<ButtonRelease-1>', element.ButtonReleaseCallBack)
|
tkbutton.bind('<ButtonRelease-1>', element.ButtonReleaseCallBack)
|
||||||
tkbutton.bind('<ButtonPress-1>', element.ButtonPressCallBack)
|
tkbutton.bind('<ButtonPress-1>', element.ButtonPressCallBack)
|
||||||
if bc != (None, None) and COLOR_SYSTEM_DEFAULT not in bc:
|
if bc != (None, None) and COLOR_SYSTEM_DEFAULT not in bc:
|
||||||
tkbutton.config(foreground=bc[0], background=bc[1], activebackground=bc[1])
|
tkbutton.config(foreground=bc[0], background=bc[1])
|
||||||
else:
|
else:
|
||||||
if bc[0] != COLOR_SYSTEM_DEFAULT:
|
if bc[0] != COLOR_SYSTEM_DEFAULT:
|
||||||
tkbutton.config(foreground=bc[0])
|
tkbutton.config(foreground=bc[0])
|
||||||
|
@ -12663,7 +12665,6 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
|
||||||
# 'Color string: {}'.format(bc),
|
# 'Color string: {}'.format(bc),
|
||||||
"Parent Window's Title: {}".format(toplevel_form.Title))
|
"Parent Window's Title: {}".format(toplevel_form.Title))
|
||||||
|
|
||||||
|
|
||||||
if bd == 0 and not running_mac():
|
if bd == 0 and not running_mac():
|
||||||
tkbutton.config(relief=tk.FLAT)
|
tkbutton.config(relief=tk.FLAT)
|
||||||
|
|
||||||
|
@ -12724,7 +12725,7 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
|
||||||
if element.DisabledButtonColor != (None, None) and element.DisabledButtonColor != (COLOR_SYSTEM_DEFAULT, COLOR_SYSTEM_DEFAULT):
|
if element.DisabledButtonColor != (None, None) and element.DisabledButtonColor != (COLOR_SYSTEM_DEFAULT, COLOR_SYSTEM_DEFAULT):
|
||||||
if element.DisabledButtonColor[0] not in (None, COLOR_SYSTEM_DEFAULT):
|
if element.DisabledButtonColor[0] not in (None, COLOR_SYSTEM_DEFAULT):
|
||||||
element.TKButton['disabledforeground'] = element.DisabledButtonColor[0]
|
element.TKButton['disabledforeground'] = element.DisabledButtonColor[0]
|
||||||
if element.MouseOverColors[1] not in (COLOR_SYSTEM_DEFAULT, None) :
|
if element.MouseOverColors[1] not in (COLOR_SYSTEM_DEFAULT, None):
|
||||||
tkbutton.config(activebackground=element.MouseOverColors[1])
|
tkbutton.config(activebackground=element.MouseOverColors[1])
|
||||||
if element.MouseOverColors[0] not in (COLOR_SYSTEM_DEFAULT, None):
|
if element.MouseOverColors[0] not in (COLOR_SYSTEM_DEFAULT, None):
|
||||||
tkbutton.config(activeforeground=element.MouseOverColors[0])
|
tkbutton.config(activeforeground=element.MouseOverColors[0])
|
||||||
|
@ -12889,7 +12890,7 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
|
||||||
justify=tk.LEFT, bd=bd, font=font)
|
justify=tk.LEFT, bd=bd, font=font)
|
||||||
element.TKButtonMenu = tkbutton
|
element.TKButtonMenu = tkbutton
|
||||||
if bc != (None, None) and bc != COLOR_SYSTEM_DEFAULT and bc[1] != COLOR_SYSTEM_DEFAULT:
|
if bc != (None, None) and bc != COLOR_SYSTEM_DEFAULT and bc[1] != COLOR_SYSTEM_DEFAULT:
|
||||||
tkbutton.config(foreground=bc[0], background=bc[1], activebackground=bc[1])
|
tkbutton.config(foreground=bc[0], background=bc[1])
|
||||||
elif bc[0] != COLOR_SYSTEM_DEFAULT:
|
elif bc[0] != COLOR_SYSTEM_DEFAULT:
|
||||||
tkbutton.config(foreground=bc[0])
|
tkbutton.config(foreground=bc[0])
|
||||||
if bd == 0 and not running_mac():
|
if bd == 0 and not running_mac():
|
||||||
|
@ -12937,7 +12938,8 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
|
||||||
top_menu.config(font=element.ItemFont)
|
top_menu.config(font=element.ItemFont)
|
||||||
|
|
||||||
AddMenuItem(top_menu, menu_def[1], element)
|
AddMenuItem(top_menu, menu_def[1], element)
|
||||||
|
if elementpad[0] == 0 or elementpad[1] == 0:
|
||||||
|
tkbutton.config(highlightthickness=0)
|
||||||
tkbutton.configure(menu=top_menu)
|
tkbutton.configure(menu=top_menu)
|
||||||
element.TKMenu = top_menu
|
element.TKMenu = top_menu
|
||||||
if element.visible is False:
|
if element.visible is False:
|
||||||
|
@ -12946,6 +12948,7 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
|
||||||
element.TKButton['state'] = 'disabled'
|
element.TKButton['state'] = 'disabled'
|
||||||
if element.Tooltip is not None:
|
if element.Tooltip is not None:
|
||||||
element.TooltipObject = ToolTip(element.TKButton, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME)
|
element.TooltipObject = ToolTip(element.TKButton, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME)
|
||||||
|
|
||||||
# ------------------------- INPUT placement element ------------------------- #
|
# ------------------------- INPUT placement element ------------------------- #
|
||||||
elif element_type == ELEM_TYPE_INPUT_TEXT:
|
elif element_type == ELEM_TYPE_INPUT_TEXT:
|
||||||
element = element # type: InputText
|
element = element # type: InputText
|
||||||
|
@ -17729,6 +17732,22 @@ def popup_menu(window, element, menu_def, title=None, location=(None, None)):
|
||||||
top_menu.invoke(0)
|
top_menu.invoke(0)
|
||||||
|
|
||||||
|
|
||||||
|
def popup_error_with_traceback(title, *messages):
|
||||||
|
"""
|
||||||
|
Show an error message and as many additoinal lines of messages as you want.
|
||||||
|
Will show the same error window as PySimpleGUI uses internally. Has a button to
|
||||||
|
take the user to the line of code you called this popup from
|
||||||
|
|
||||||
|
:param title:
|
||||||
|
:type title: str
|
||||||
|
:param messages: A variable number of lines of messages you wish to show your user
|
||||||
|
:type messages: *Any
|
||||||
|
"""
|
||||||
|
|
||||||
|
# For now, call the function that PySimpleGUI uses internally
|
||||||
|
_error_popup_with_traceback(str(title), *messages)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def _error_popup_with_traceback(title, *args):
|
def _error_popup_with_traceback(title, *args):
|
||||||
if SUPPRESS_ERROR_POPUPS:
|
if SUPPRESS_ERROR_POPUPS:
|
||||||
|
@ -17762,8 +17781,13 @@ def _error_popup_with_traceback(title, *args):
|
||||||
def _error_popup_with_code(title, filename=None, line_num=None, *args):
|
def _error_popup_with_code(title, filename=None, line_num=None, *args):
|
||||||
layout = [[Text('ERROR'), Text(title)],
|
layout = [[Text('ERROR'), Text(title)],
|
||||||
[Image(data=_random_error_emoji())]]
|
[Image(data=_random_error_emoji())]]
|
||||||
# make max length of line be 90 chars and allow the hieight to vary based on number of needed lines
|
# make max length of line be 90 chars and allow the height to vary based on number of needed lines
|
||||||
layout += [[Text(str(msg), size=(min(90, len(str(msg))),None))] for msg in args]
|
lines = [str(msg).split('\n') for msg in args]
|
||||||
|
max_line_len = 0
|
||||||
|
for line in lines:
|
||||||
|
max_line_len = max(max_line_len, max([len(s) for s in line]))
|
||||||
|
|
||||||
|
layout += [[Text(str(msg), size=(min(max_line_len, 90), None))] for msg in args]
|
||||||
|
|
||||||
layout += [[Button('Close'), Button('Take me to error')]]
|
layout += [[Button('Close'), Button('Take me to error')]]
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue