1
0
mirror of https://github.com/EDCD/EDMarketConnector.git synced 2025-04-13 07:47:14 +03:00

[2186] Main, Dashboard, Prefs

This commit is contained in:
David Sangrey 2024-03-27 19:26:25 -04:00
parent 93d26e07e0
commit 27093d8862
No known key found for this signature in database
GPG Key ID: 3AEADBB0186884BC
4 changed files with 161 additions and 362 deletions

View File

@ -496,7 +496,6 @@ class AppWindow:
plug.load_plugins(master)
if sys.platform != 'darwin':
if sys.platform == 'win32':
self.w.wm_iconbitmap(default='EDMarketConnector.ico')
@ -599,7 +598,7 @@ class AppWindow:
self.theme_button = tk.Label(
frame,
name='themed_update_button',
width=32 if sys.platform == 'darwin' else 28,
width=28,
state=tk.DISABLED
)
@ -633,46 +632,6 @@ class AppWindow:
self.updater = update.Updater(tkroot=self.w)
self.updater.check_for_updates() # Sparkle / WinSparkle does this automatically for packaged apps
if sys.platform == 'darwin':
# Can't handle (de)iconify if topmost is set, so suppress iconify button
# http://wiki.tcl.tk/13428 and p15 of
# https://developer.apple.com/legacy/library/documentation/Carbon/Conceptual/HandlingWindowsControls/windowscontrols.pdf
root.call('tk::unsupported::MacWindowStyle', 'style', root, 'document', 'closeBox resizable')
# https://www.tcl.tk/man/tcl/TkCmd/menu.htm
self.system_menu = tk.Menu(self.menubar, name='apple')
self.system_menu.add_command(command=lambda: self.w.call('tk::mac::standardAboutPanel'))
self.system_menu.add_command(command=lambda: self.updater.check_for_updates())
self.menubar.add_cascade(menu=self.system_menu)
self.file_menu = tk.Menu(self.menubar, name='file')
self.file_menu.add_command(command=self.save_raw)
self.menubar.add_cascade(menu=self.file_menu)
self.edit_menu = tk.Menu(self.menubar, name='edit')
self.edit_menu.add_command(accelerator='Command-c', state=tk.DISABLED, command=self.copy)
self.menubar.add_cascade(menu=self.edit_menu)
self.w.bind('<Command-c>', self.copy)
self.view_menu = tk.Menu(self.menubar, name='view')
self.view_menu.add_command(command=lambda: stats.StatsDialog(self.w, self.status))
self.menubar.add_cascade(menu=self.view_menu)
window_menu = tk.Menu(self.menubar, name='window')
self.menubar.add_cascade(menu=window_menu)
self.help_menu = tk.Menu(self.menubar, name='help')
self.w.createcommand("::tk::mac::ShowHelp", self.help_general)
self.help_menu.add_command(command=self.help_troubleshooting)
self.help_menu.add_command(command=self.help_report_a_bug)
self.help_menu.add_command(command=self.help_privacy)
self.help_menu.add_command(command=self.help_releases)
self.menubar.add_cascade(menu=self.help_menu)
self.w['menu'] = self.menubar
# https://www.tcl.tk/man/tcl/TkCmd/tk_mac.htm
self.w.call('set', 'tk::mac::useCompatibilityMetrics', '0')
self.w.createcommand('tkAboutDialog', lambda: self.w.call('tk::mac::standardAboutPanel'))
self.w.createcommand("::tk::mac::Quit", self.onexit)
self.w.createcommand("::tk::mac::ShowPreferences", lambda: prefs.PreferencesDialog(self.w, self.postprefs))
self.w.createcommand("::tk::mac::ReopenApplication", self.w.deiconify) # click on app in dock = restore
self.w.protocol("WM_DELETE_WINDOW", self.w.withdraw) # close button shouldn't quit app
self.w.resizable(tk.FALSE, tk.FALSE) # Can't be only resizable on one axis
else:
self.file_menu = self.view_menu = tk.Menu(self.menubar, tearoff=tk.FALSE)
self.file_menu.add_command(command=lambda: stats.StatsDialog(self.w, self.status))
self.file_menu.add_command(command=self.save_raw)
@ -770,11 +729,7 @@ class AppWindow:
if config.get_str('geometry'):
match = re.match(r'\+([\-\d]+)\+([\-\d]+)', config.get_str('geometry'))
if match:
if sys.platform == 'darwin':
# http://core.tcl.tk/tk/tktview/c84f660833546b1b84e7
if int(match.group(2)) >= 0:
self.w.geometry(config.get_str('geometry'))
elif sys.platform == 'win32':
if sys.platform == 'win32':
# Check that the titlebar will be at least partly on screen
import ctypes
from ctypes.wintypes import POINT
@ -910,27 +865,6 @@ class AppWindow:
self.system_label['text'] = _('System') + ':' # LANG: Label for 'System' line in main UI
self.station_label['text'] = _('Station') + ':' # LANG: Label for 'Station' line in main UI
self.button['text'] = self.theme_button['text'] = _('Update') # LANG: Update button in main window
if sys.platform == 'darwin':
self.menubar.entryconfigure(1, label=_('File')) # LANG: 'File' menu title on OSX
self.menubar.entryconfigure(2, label=_('Edit')) # LANG: 'Edit' menu title on OSX
self.menubar.entryconfigure(3, label=_('View')) # LANG: 'View' menu title on OSX
self.menubar.entryconfigure(4, label=_('Window')) # LANG: 'Window' menu title on OSX
self.menubar.entryconfigure(5, label=_('Help')) # LANG: Help' menu title on OSX
self.system_menu.entryconfigure(
0,
label=_("About {APP}").format(APP=applongname) # LANG: App menu entry on OSX
)
self.system_menu.entryconfigure(1, label=_("Check for Updates...")) # LANG: Help > Check for Updates...
self.file_menu.entryconfigure(0, label=_('Save Raw Data...')) # LANG: File > Save Raw Data...
self.view_menu.entryconfigure(0, label=_('Status')) # LANG: File > Status
self.help_menu.entryconfigure(1, label=_('Documentation')) # LANG: Help > Documentation
self.help_menu.entryconfigure(2, label=_('Troubleshooting')) # LANG: Help > Troubleshooting
self.help_menu.entryconfigure(3, label=_('Report A Bug')) # LANG: Help > Report A Bug
self.help_menu.entryconfigure(4, label=_('Privacy Policy')) # LANG: Help > Privacy Policy
self.help_menu.entryconfigure(5, label=_('Release Notes')) # LANG: Help > Release Notes
self.help_menu.entryconfigure(6, label=_('Open Log Folder')) # LANG: Help > Open Log Folder
else:
self.menubar.entryconfigure(1, label=_('File')) # LANG: 'File' menu title
self.menubar.entryconfigure(2, label=_('Edit')) # LANG: 'Edit' menu title
self.menubar.entryconfigure(3, label=_('Help')) # LANG: 'Help' menu title
@ -975,11 +909,6 @@ class AppWindow:
self.button['state'] = self.theme_button['state'] = tk.DISABLED
if sys.platform == 'darwin':
self.view_menu.entryconfigure(0, state=tk.DISABLED) # Status
self.file_menu.entryconfigure(0, state=tk.DISABLED) # Save Raw Data
else:
self.file_menu.entryconfigure(0, state=tk.DISABLED) # Status
self.file_menu.entryconfigure(1, state=tk.DISABLED) # Save Raw Data
@ -989,11 +918,6 @@ class AppWindow:
# LANG: Successfully authenticated with the Frontier website
self.status['text'] = _('Authentication successful')
if sys.platform == 'darwin':
self.view_menu.entryconfigure(0, state=tk.NORMAL) # Status
self.file_menu.entryconfigure(0, state=tk.NORMAL) # Save Raw Data
else:
self.file_menu.entryconfigure(0, state=tk.NORMAL) # Status
self.file_menu.entryconfigure(1, state=tk.NORMAL) # Save Raw Data
@ -1666,11 +1590,6 @@ class AppWindow:
companion.session.auth_callback()
# LANG: Successfully authenticated with the Frontier website
self.status['text'] = _('Authentication successful')
if sys.platform == 'darwin':
self.view_menu.entryconfigure(0, state=tk.NORMAL) # Status
self.file_menu.entryconfigure(0, state=tk.NORMAL) # Save Raw Data
else:
self.file_menu.entryconfigure(0, state=tk.NORMAL) # Status
self.file_menu.entryconfigure(1, state=tk.NORMAL) # Save Raw Data
@ -1831,7 +1750,7 @@ class AppWindow:
# position over parent
# http://core.tcl.tk/tk/tktview/c84f660833546b1b84e7
if sys.platform != 'darwin' or parent.winfo_rooty() > 0:
if parent.winfo_rooty() > 0:
self.geometry(f'+{parent.winfo_rootx():d}+{parent.winfo_rooty():d}')
# remove decoration
@ -1916,9 +1835,6 @@ class AppWindow:
"""
default_extension: str = ''
if sys.platform == 'darwin':
default_extension = '.json'
timestamp: str = strftime('%Y-%m-%dT%H.%M.%S', localtime())
f = tkinter.filedialog.asksaveasfilename(
parent=self.w,
@ -1954,7 +1870,7 @@ class AppWindow:
config.set_shutdown() # Signal we're in shutdown now.
# http://core.tcl.tk/tk/tktview/c84f660833546b1b84e7
if sys.platform != 'darwin' or self.w.winfo_rooty() > 0:
if self.w.winfo_rooty() > 0:
x, y = self.w.geometry().split('+')[1:3] # e.g. '212x170+2881+1267'
config.set('geometry', f'+{x}+{y}')

View File

@ -20,7 +20,7 @@ from EDMCLogging import get_main_logger
logger = get_main_logger()
if sys.platform in ('darwin', 'win32'):
if sys.platform == 'win32':
from watchdog.events import FileSystemEventHandler
from watchdog.observers import Observer
else:

View File

@ -78,7 +78,7 @@ class Label(tk.Label):
def __init__(self, master: ttk.Frame | None = None, **kw):
# This format chosen over `sys.platform in (...)` as mypy and friends dont understand that
if sys.platform in ('darwin', 'win32'):
if sys.platform == 'win32':
kw['foreground'] = kw.pop('foreground', PAGEFG)
kw['background'] = kw.pop('background', PAGEBG)
else:

133
prefs.py
View File

@ -18,7 +18,7 @@ from typing import TYPE_CHECKING, Any, Callable, Optional, Type
import myNotebook as nb # noqa: N813
import plug
from config import applongname, appversion_nobuild, config
from config import appversion_nobuild, config
from EDMCLogging import edmclogger, get_main_logger
from constants import appname
from hotkey import hotkeymgr
@ -49,9 +49,6 @@ def help_open_log_folder() -> None:
if sys.platform.startswith('win'):
# On Windows, use the "start" command to open the folder
system(f'start "" "{logfile_loc}"')
elif sys.platform.startswith('darwin'):
# On macOS, use the "open" command to open the folder
system(f'open "{logfile_loc}"')
elif sys.platform.startswith('linux'):
# On Linux, use the "xdg-open" command to open the folder
system(f'xdg-open "{logfile_loc}"')
@ -172,32 +169,7 @@ class AutoInc(contextlib.AbstractContextManager):
return None
if sys.platform == 'darwin':
import objc # type: ignore
from Foundation import NSFileManager # type: ignore
try:
from ApplicationServices import ( # type: ignore
AXIsProcessTrusted, AXIsProcessTrustedWithOptions, kAXTrustedCheckOptionPrompt
)
except ImportError:
HIServices = objc.loadBundle(
'HIServices',
globals(),
'/System/Library/Frameworks/ApplicationServices.framework/Frameworks/HIServices.framework'
)
objc.loadBundleFunctions(
HIServices,
globals(),
[('AXIsProcessTrusted', 'B'), ('AXIsProcessTrustedWithOptions', 'B@')]
)
objc.loadBundleVariables(HIServices, globals(), [('kAXTrustedCheckOptionPrompt', '@^{__CFString=}')])
was_accessible_at_launch = AXIsProcessTrusted() # type: ignore
elif sys.platform == 'win32':
if sys.platform == 'win32':
import ctypes
import winreg
from ctypes.wintypes import HINSTANCE, HWND, LPCWSTR, LPWSTR, MAX_PATH, POINT, RECT, SIZE, UINT
@ -251,11 +223,6 @@ class PreferencesDialog(tk.Toplevel):
self.parent = parent
self.callback = callback
if sys.platform == 'darwin':
# LANG: File > Preferences menu entry for macOS
self.title(_('Preferences'))
else:
# LANG: File > Settings (macOS)
self.title(_('Settings'))
@ -263,7 +230,7 @@ class PreferencesDialog(tk.Toplevel):
self.transient(parent)
# position over parent
if sys.platform != 'darwin' or parent.winfo_rooty() > 0: # http://core.tcl.tk/tk/tktview/c84f660833546b1b84e7
if parent.winfo_rooty() > 0: # http://core.tcl.tk/tk/tktview/c84f660833546b1b84e7
# TODO this is fixed supposedly.
self.geometry(f'+{parent.winfo_rootx()}+{parent.winfo_rooty()}')
@ -271,10 +238,6 @@ class PreferencesDialog(tk.Toplevel):
if sys.platform == 'win32':
self.attributes('-toolwindow', tk.TRUE)
elif sys.platform == 'darwin':
# http://wiki.tcl.tk/13428
parent.call('tk::unsupported::MacWindowStyle', 'style', self, 'utility')
self.resizable(tk.FALSE, tk.FALSE)
self.cmdr: str | bool | None = False # Note if Cmdr changes in the Journal
@ -302,10 +265,6 @@ class PreferencesDialog(tk.Toplevel):
self.__setup_appearance_tab(notebook)
self.__setup_plugin_tab(notebook)
if sys.platform == 'darwin':
self.protocol("WM_DELETE_WINDOW", self.apply) # close button applies changes
else:
buttonframe = ttk.Frame(frame)
buttonframe.grid(padx=self.PADX, pady=self.PADX, sticky=tk.NSEW)
buttonframe.columnconfigure(0, weight=1)
@ -405,10 +364,6 @@ class PreferencesDialog(tk.Toplevel):
self.outdir_entry = nb.Entry(output_frame, takefocus=False)
self.outdir_entry.grid(columnspan=2, padx=self.PADX, pady=self.BOXY, sticky=tk.EW, row=row.get())
if sys.platform == 'darwin':
text = (_('Change...')) # LANG: macOS Preferences - files location selection button
else:
text = (_('Browse...')) # LANG: NOT-macOS Settings - files location selection button
self.outbutton = nb.Button(
@ -455,10 +410,6 @@ class PreferencesDialog(tk.Toplevel):
self.logdir_entry.grid(columnspan=4, padx=self.PADX, pady=self.BOXY, sticky=tk.EW, row=row.get())
if sys.platform == 'darwin':
text = (_('Change...')) # LANG: macOS Preferences - files location selection button
else:
text = (_('Browse...')) # LANG: NOT-macOS Setting - files location selection button
with row as cur_row:
@ -499,7 +450,7 @@ class PreferencesDialog(tk.Toplevel):
variable=self.capi_fleetcarrier
).grid(columnspan=4, padx=self.BUTTONX, pady=self.PADY, sticky=tk.W, row=row.get())
if sys.platform in ('darwin', 'win32'):
if sys.platform == 'win32':
ttk.Separator(config_frame, orient=tk.HORIZONTAL).grid(
columnspan=4, padx=self.PADX, pady=self.SEPY, sticky=tk.EW, row=row.get()
)
@ -511,42 +462,14 @@ class PreferencesDialog(tk.Toplevel):
with row as cur_row:
nb.Label(
config_frame,
text=_('Keyboard shortcut') if # LANG: Hotkey/Shortcut settings prompt on OSX
sys.platform == 'darwin' else
_('Hotkey') # LANG: Hotkey/Shortcut settings prompt on Windows
text=_('Hotkey') # LANG: Hotkey/Shortcut settings prompt on Windows
).grid(padx=self.PADX, pady=self.PADY, sticky=tk.W, row=cur_row)
if sys.platform == 'darwin' and not was_accessible_at_launch:
if AXIsProcessTrusted():
# Shortcut settings prompt on OSX
nb.Label(
config_frame,
# LANG: macOS Preferences > Configuration - restart the app message
text=_('Re-start {APP} to use shortcuts').format(APP=applongname),
foreground='firebrick'
).grid(padx=self.PADX, pady=self.PADY, sticky=tk.W, row=cur_row)
else:
# Shortcut settings prompt on OSX
nb.Label(
config_frame,
# LANG: macOS - Configuration - need to grant the app permission for keyboard shortcuts
text=_('{APP} needs permission to use shortcuts').format(APP=applongname),
foreground='firebrick'
).grid(columnspan=4, padx=self.PADX, pady=self.PADY, sticky=tk.W, row=cur_row)
# LANG: Shortcut settings button on OSX
nb.Button(config_frame, text=_('Open System Preferences'), command=self.enableshortcuts).grid(
padx=self.PADX, pady=self.BOXY, sticky=tk.E, row=cur_row
)
else:
self.hotkey_text = nb.Entry(config_frame, width=(
20 if sys.platform == 'darwin' else 30), justify=tk.CENTER)
self.hotkey_text = nb.Entry(config_frame, width=30, justify=tk.CENTER)
self.hotkey_text.insert(
0,
# No hotkey/shortcut currently defined
# TODO: display Only shows up on darwin or windows
# TODO: display Only shows up on windows
# LANG: No hotkey/shortcut set
hotkeymgr.display(self.hotkey_code, self.hotkey_mods) if self.hotkey_code else _('None')
)
@ -1070,14 +993,6 @@ class PreferencesDialog(tk.Toplevel):
def tabchanged(self, event: tk.Event) -> None:
"""Handle preferences active tab changing."""
self.outvarchanged()
if sys.platform == 'darwin':
# Hack to recompute size so that buttons show up under Mojave
notebook = event.widget
frame = self.nametowidget(notebook.winfo_parent())
temp = nb.Label(frame)
temp.grid()
temp.update_idletasks()
temp.destroy()
def outvarchanged(self, event: Optional[tk.Event] = None) -> None:
"""Handle Output tab variable changes."""
@ -1139,16 +1054,6 @@ class PreferencesDialog(tk.Toplevel):
entryfield.insert(0, '\\'.join(display))
# None if path doesn't exist
elif sys.platform == 'darwin' and NSFileManager.defaultManager().componentsToDisplayForPath_(pathvar.get()):
if pathvar.get().startswith(config.home):
display = ['~'] + NSFileManager.defaultManager().componentsToDisplayForPath_(pathvar.get())[
len(NSFileManager.defaultManager().componentsToDisplayForPath_(config.home)):
]
else:
display = NSFileManager.defaultManager().componentsToDisplayForPath_(pathvar.get())
entryfield.insert(0, '/'.join(display))
else:
if pathvar.get().startswith(config.home):
entryfield.insert(0, '~' + pathvar.get()[len(config.home):])
@ -1288,7 +1193,7 @@ class PreferencesDialog(tk.Toplevel):
config.set('capi_fleetcarrier', self.capi_fleetcarrier.get())
if sys.platform in ('darwin', 'win32'):
if sys.platform == 'win32':
config.set('hotkey_code', self.hotkey_code)
config.set('hotkey_mods', self.hotkey_mods)
config.set('hotkey_always', int(not self.hotkey_only.get()))
@ -1333,25 +1238,3 @@ class PreferencesDialog(tk.Toplevel):
self.parent.wm_attributes('-topmost', 1 if config.get_int('always_ontop') else 0)
self.destroy()
if sys.platform == 'darwin':
def enableshortcuts(self) -> None:
"""Set up macOS preferences shortcut."""
self.apply()
# popup System Preferences dialog
try:
# http://stackoverflow.com/questions/6652598/cocoa-button-opens-a-system-preference-page/6658201
from ScriptingBridge import SBApplication # type: ignore
sysprefs = 'com.apple.systempreferences'
prefs = SBApplication.applicationWithBundleIdentifier_(sysprefs)
pane = [x for x in prefs.panes() if x.id() == 'com.apple.preference.security'][0]
prefs.setCurrentPane_(pane)
anchor = [x for x in pane.anchors() if x.name() == 'Privacy_Accessibility'][0]
anchor.reveal()
prefs.activate()
except Exception:
AXIsProcessTrustedWithOptions({kAXTrustedCheckOptionPrompt: True})
if not config.shutting_down:
self.parent.event_generate('<<Quit>>', when="tail")