From c8f2b6018cf0fc7e5244ece6d2a52052c19fee40 Mon Sep 17 00:00:00 2001 From: David Sangrey Date: Wed, 24 Apr 2024 20:03:04 -0400 Subject: [PATCH 01/10] [1173] Right-Click Provider Options --- EDMarketConnector.py | 10 ++++---- L10n/en.template | 3 +++ ttkHyperlinkLabel.py | 56 +++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 63 insertions(+), 6 deletions(-) diff --git a/EDMarketConnector.py b/EDMarketConnector.py index 09e6fc4e..62bb4f5d 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -515,13 +515,13 @@ class AppWindow: self.cmdr_label = tk.Label(frame, name='cmdr_label') self.cmdr = tk.Label(frame, compound=tk.RIGHT, anchor=tk.W, name='cmdr') self.ship_label = tk.Label(frame, name='ship_label') - self.ship = HyperlinkLabel(frame, compound=tk.RIGHT, url=self.shipyard_url, name='ship') + self.ship = HyperlinkLabel(frame, compound=tk.RIGHT, url=self.shipyard_url, name='ship', popup_copy=True) self.suit_label = tk.Label(frame, name='suit_label') self.suit = tk.Label(frame, compound=tk.RIGHT, anchor=tk.W, name='suit') self.system_label = tk.Label(frame, name='system_label') self.system = HyperlinkLabel(frame, compound=tk.RIGHT, url=self.system_url, popup_copy=True, name='system') self.station_label = tk.Label(frame, name='station_label') - self.station = HyperlinkLabel(frame, compound=tk.RIGHT, url=self.station_url, name='station') + self.station = HyperlinkLabel(frame, compound=tk.RIGHT, url=self.station_url, name='station', popup_copy=True) # system and station text is set/updated by the 'provider' plugins # edsm and inara. Look for: # @@ -1627,7 +1627,7 @@ class AppWindow: hotkeymgr.play_bad() def shipyard_url(self, shipname: str) -> str | None: - """Despatch a ship URL to the configured handler.""" + """Dispatch a ship URL to the configured handler.""" if not (loadout := monitor.ship()): logger.warning('No ship loadout, aborting.') return '' @@ -1654,13 +1654,13 @@ class AppWindow: return f'file://localhost/{file_name}' def system_url(self, system: str) -> str | None: - """Despatch a system URL to the configured handler.""" + """Dispatch a system URL to the configured handler.""" return plug.invoke( config.get_str('system_provider', default='EDSM'), 'EDSM', 'system_url', monitor.state['SystemName'] ) def station_url(self, station: str) -> str | None: - """Despatch a station URL to the configured handler.""" + """Dispatch a station URL to the configured handler.""" return plug.invoke( config.get_str('station_provider', default='EDSM'), 'EDSM', 'station_url', monitor.state['SystemName'], monitor.state['StationName'] diff --git a/L10n/en.template b/L10n/en.template index 200743c8..5a78cba2 100644 --- a/L10n/en.template +++ b/L10n/en.template @@ -782,3 +782,6 @@ /* myNotebook.py: Can't Paste Images or Files in Text; */ "Cannot paste non-text content." = "Cannot paste non-text content."; + +/* ttkHyperlinkLabel.py: Open Element In Selected Provider; */ +"Open in {URL}" = "Open in {URL}"; \ No newline at end of file diff --git a/ttkHyperlinkLabel.py b/ttkHyperlinkLabel.py index d026f619..3bb878a6 100644 --- a/ttkHyperlinkLabel.py +++ b/ttkHyperlinkLabel.py @@ -19,14 +19,17 @@ In addition to standard ttk.Label arguments, takes the following arguments: May be imported by plugins """ from __future__ import annotations - +from functools import partial import sys import tkinter as tk import webbrowser from tkinter import font as tk_font from tkinter import ttk from typing import Any +import plug +from config import config, logger from l10n import translations as tr +from monitor import monitor class HyperlinkLabel(tk.Label or ttk.Label): # type: ignore @@ -64,6 +67,57 @@ class HyperlinkLabel(tk.Label or ttk.Label): # type: ignore text=kw.get('text'), font=kw.get('font', ttk.Style().lookup('TLabel', 'font'))) + # Add Menu Options + self.plug_options = kw.pop('plug_options', None) + self.name = kw.get('name', None) + if self.name == 'ship' and not bool(config.get_int("use_alt_shipyard_open")): + self.menu.add_separator() + for url in plug.provides('shipyard_url'): + self.menu.add_command( + label=tr.tl("Open in {URL}").format(URL=url), # LANG: Open Element In Selected Provider + command=partial(self.open_shipyard, url) + ) + + if self.name == 'station': + self.menu.add_separator() + for url in plug.provides('station_url'): + self.menu.add_command( + label=tr.tl("Open in {URL}").format(URL=url), # LANG: Open Element In Selected Provider + command=partial(self.open_station, url) + ) + + if self.name == 'system': + self.menu.add_separator() + for url in plug.provides('system_url'): + self.menu.add_command( + label=tr.tl("Open in {URL}").format(URL=url), # LANG: Open Element In Selected Provider + command=partial(self.open_system, url) + ) + + def open_shipyard(self, url: str): + """Open the Current Ship Loadout in the Selected Provider.""" + if loadout := monitor.ship(): + opener = plug.invoke(url, 'EDSY', 'shipyard_url', loadout, monitor.is_beta) + if opener: + return webbrowser.open(opener) + logger.warning('No ship loadout, aborting.') + return '' + + def open_system(self, url: str): + """Open the Current System in the Selected Provider.""" + opener = plug.invoke(url, 'EDSM', 'system_url', monitor.state['SystemName']) + if opener: + return webbrowser.open(opener) + + def open_station(self, url: str): + """Open the Current Station in the Selected Provider.""" + opener = plug.invoke( + url, 'EDSM', 'station_url', + monitor.state['SystemName'], monitor.state['StationName'] + ) + if opener: + return webbrowser.open(opener) + def configure( # noqa: CCR001 self, cnf: dict[str, Any] | None = None, **kw: Any ) -> dict[str, tuple[str, str, str, Any, Any]] | None: From 770c0ed3a5b0f2f453aa78f7294f971c4814e538 Mon Sep 17 00:00:00 2001 From: David Sangrey Date: Fri, 26 Apr 2024 00:41:58 -0400 Subject: [PATCH 02/10] [2203] Catch Irrecoverable Errors --- EDMarketConnector.py | 26 +++++++++++++++++++++++++- L10n/en.template | 6 ++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/EDMarketConnector.py b/EDMarketConnector.py index 09e6fc4e..8ec3ab75 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -11,9 +11,11 @@ from __future__ import annotations import argparse import html import locale +import os import pathlib import queue import re +import signal import subprocess import sys import threading @@ -2226,7 +2228,29 @@ sys.path: {sys.path}''' if theme.default_ui_scale is not None: root.tk.call('tk', 'scaling', theme.default_ui_scale * float(ui_scale) / 100.0) - app = AppWindow(root) + try: + app = AppWindow(root) + except Exception as err: + logger.exception(f"EDMC Critical Error: {err}") + title = tr.tl("Error") # LANG: Generic error prefix + message = tr.tl( # LANG: EDMC Critical Error Notification + "EDSM encountered a critical error, and cannot recover. EDMC is shutting down for its own protection!" + ) + err = f"{err.__class__.__name__}: {err}" # type: ignore # hijacking the existing exception detection + detail = tr.tl( # LANG: EDMC Critical Error Details + r"Here's what EDMC Detected:\r\n\r\n{ERR}\r\n\r\nDo you want to file a Bug Report on GitHub?" + ).format(ERR=err) + detail = detail.replace('\\n', '\n') + detail = detail.replace('\\r', '\r') + msg = tk.messagebox.askyesno( + title=title, message=message, detail=detail, icon=tkinter.messagebox.ERROR, type=tkinter.messagebox.YESNO + ) + if msg: + webbrowser.open( + "https://github.com/EDCD/EDMarketConnector/issues/new?" + "assignees=&labels=bug%2C+unconfirmed&projects=&template=bug_report.md&title=" + ) + os.kill(os.getpid(), signal.SIGTERM) def messagebox_broken_plugins(): """Display message about 'broken' plugins that failed to load.""" diff --git a/L10n/en.template b/L10n/en.template index 200743c8..b2c46d7c 100644 --- a/L10n/en.template +++ b/L10n/en.template @@ -36,6 +36,12 @@ /* companion.py: Failed to get Access Token from Frontier Auth service; In files: companion.py:508; */ "Error: unable to get token" = "Error: unable to get token"; +/* EDMarketConnector.py: EDMC Critical Error Notification; */ +"EDSM encountered a critical error, and cannot recover. EDMC is shutting down for its own protection!" = "EDSM encountered a critical error, and cannot recover. EDMC is shutting down for its own protection!"; + +/* EDMarketConnector.py: EDMC Critical Error Details; */ +"Here's what EDMC Detected:\r\n\r\n{ERR}\r\n\r\nDo you want to file a Bug Report on GitHub?" = "Here's what EDMC Detected:\r\n\r\n{ERR}\r\n\r\nDo you want to file a Bug Report on GitHub?"; + /* companion.py: Frontier CAPI returned 418, meaning down for maintenance; In files: companion.py:844; */ "Frontier CAPI down for maintenance" = "Frontier CAPI down for maintenance"; From 8b116516a2238da8268e4b4549138185052d6fcf Mon Sep 17 00:00:00 2001 From: David Sangrey Date: Fri, 26 Apr 2024 00:56:34 -0400 Subject: [PATCH 03/10] [2203] Simplify Duplicate Running Message --- EDMarketConnector.py | 23 ++++------------------- 1 file changed, 4 insertions(+), 19 deletions(-) diff --git a/EDMarketConnector.py b/EDMarketConnector.py index 8ec3ab75..45bc28c7 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -338,29 +338,14 @@ if __name__ == '__main__': # noqa: C901 def already_running_popup(): """Create the "already running" popup.""" - import tkinter as tk - from tkinter import ttk + from tkinter import messagebox # Check for CL arg that suppresses this popup. if args.suppress_dupe_process_popup: sys.exit(0) - root = tk.Tk(className=appname.lower()) - - frame = tk.Frame(root) - frame.grid(row=1, column=0, sticky=tk.NSEW) - - label = tk.Label(frame, text='An EDMarketConnector.exe process was already running, exiting.') - label.grid(row=1, column=0, sticky=tk.NSEW) - - button = ttk.Button(frame, text='OK', command=lambda: sys.exit(0)) - button.grid(row=2, column=0, sticky=tk.S) - - try: - root.mainloop() - except KeyboardInterrupt: - logger.info("Ctrl+C Detected, Attempting Clean Shutdown") - sys.exit() - logger.info('Exiting') + already_running_msg = "An EDMarketConnector process was already running, exiting." + messagebox.showerror(title=appname, message=already_running_msg) + sys.exit(0) journal_lock = JournalLock() locked = journal_lock.obtain_lock() From 3589bdd8e26c506189aa8e3892f1e6435a77f5d8 Mon Sep 17 00:00:00 2001 From: David Sangrey Date: Fri, 26 Apr 2024 00:57:23 -0400 Subject: [PATCH 04/10] [Minor] Why Use Two Line When One Line Do Trick --- EDMarketConnector.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/EDMarketConnector.py b/EDMarketConnector.py index 45bc28c7..92ab3fe8 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -343,8 +343,7 @@ if __name__ == '__main__': # noqa: C901 if args.suppress_dupe_process_popup: sys.exit(0) - already_running_msg = "An EDMarketConnector process was already running, exiting." - messagebox.showerror(title=appname, message=already_running_msg) + messagebox.showerror(title=appname, message="An EDMarketConnector process was already running, exiting.") sys.exit(0) journal_lock = JournalLock() From 3d9e46d730dd55376da102778aa870f27410e8ce Mon Sep 17 00:00:00 2001 From: David Sangrey Date: Fri, 26 Apr 2024 12:41:57 -0400 Subject: [PATCH 05/10] [Minor] Push Back Deprecation Date While these modules are deprecated, one minor version is a little too quick to remove. Pushes back to 6.0 for plugin developer compatibilty's sake. --- myNotebook.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/myNotebook.py b/myNotebook.py index 43acfebd..8a3cf901 100644 --- a/myNotebook.py +++ b/myNotebook.py @@ -121,7 +121,7 @@ class EntryMenu(ttk.Entry): class Entry(EntryMenu): """Custom ttk.Entry class to fix some display issues.""" - # DEPRECATED: Migrate to EntryMenu. Will remove in 5.12 or later. + # DEPRECATED: Migrate to EntryMenu. Will remove in 6.0 or later. def __init__(self, master: ttk.Frame | None = None, **kw): EntryMenu.__init__(self, master, **kw) @@ -139,7 +139,7 @@ class Button(ttk.Button): class ColoredButton(tk.Button): """Custom tk.Button class to fix some display issues.""" - # DEPRECATED: Migrate to tk.Button. Will remove in 5.12 or later. + # DEPRECATED: Migrate to tk.Button. Will remove in 6.0 or later. def __init__(self, master: ttk.Frame | None = None, **kw): tk.Button.__init__(self, master, **kw) From e573b8996647ccda1555e6bd6af5c694c333b630 Mon Sep 17 00:00:00 2001 From: David Sangrey Date: Sat, 27 Apr 2024 14:58:03 -0400 Subject: [PATCH 06/10] [1654] Updated setCommanderShip entry --- plugins/inara.py | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/plugins/inara.py b/plugins/inara.py index 810f7523..47c857e6 100644 --- a/plugins/inara.py +++ b/plugins/inara.py @@ -553,23 +553,6 @@ def journal_entry( # noqa: C901, CCR001 # Ship change if event_name == 'Loadout' and this.shipswap: - cur_ship = { - 'shipType': state['ShipType'], - 'shipGameID': state['ShipID'], - 'shipName': state['ShipName'], # Can be None - 'shipIdent': state['ShipIdent'], # Can be None - 'isCurrentShip': True, - } - - if state['HullValue']: - cur_ship['shipHullValue'] = state['HullValue'] - - if state['ModulesValue']: - cur_ship['shipModulesValue'] = state['ModulesValue'] - - cur_ship['shipRebuyCost'] = state['Rebuy'] - new_add_event('setCommanderShip', entry['timestamp'], cur_ship) - this.loadout = make_loadout(state) new_add_event('setCommanderShipLoadout', entry['timestamp'], this.loadout) this.shipswap = False @@ -857,7 +840,7 @@ def journal_entry( # noqa: C901, CCR001 for ship in this.fleet: new_add_event('setCommanderShip', entry['timestamp'], ship) # Loadout - if event_name == 'Loadout' and not this.newsession: + if event_name == 'Loadout': loadout = make_loadout(state) if this.loadout != loadout: this.loadout = loadout @@ -871,6 +854,26 @@ def journal_entry( # noqa: C901, CCR001 new_add_event('setCommanderShipLoadout', entry['timestamp'], this.loadout) + cur_ship = { + 'shipType': state['ShipType'], + 'shipGameID': state['ShipID'], + 'shipName': state['ShipName'], # Can be None + 'shipIdent': state['ShipIdent'], # Can be None + 'isCurrentShip': True, + 'shipMaxJumpRange': entry['MaxJumpRange'], + 'shipCargoCapacity': entry['CargoCapacity'] + } + if state['HullValue']: + cur_ship['shipHullValue'] = state['HullValue'] + + if state['ModulesValue']: + cur_ship['shipModulesValue'] = state['ModulesValue'] + + if state['Rebuy']: + cur_ship['shipRebuyCost'] = state['Rebuy'] + + new_add_event('setCommanderShip', entry['timestamp'], cur_ship) + # Stored modules if event_name == 'StoredModules': items = {mod['StorageSlot']: mod for mod in entry['Items']} # Impose an order From f03ae7809f1591322543f332a8a28b7ff28673b4 Mon Sep 17 00:00:00 2001 From: David Sangrey Date: Sat, 27 Apr 2024 15:27:22 -0400 Subject: [PATCH 07/10] [2166] Update Watchdog Type Hints Watchdog 4.0.0 included an update to the public API where FileSystemEvent, and subclasses, are now dataclasses, and their repr() has changed. As such, (insofar as I can tell) the FileCreatedEvent is now a FileSystemEvent. MyPy also suggests that this is a FileSystemEvent as well. --- monitor.py | 6 +++--- requirements.txt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/monitor.py b/monitor.py index 02b7f91c..1fd8a1d8 100644 --- a/monitor.py +++ b/monitor.py @@ -42,7 +42,7 @@ if sys.platform == 'win32': import ctypes from ctypes.wintypes import BOOL, HWND, LPARAM, LPWSTR - from watchdog.events import FileCreatedEvent, FileSystemEventHandler + from watchdog.events import FileSystemEventHandler, FileSystemEvent from watchdog.observers import Observer from watchdog.observers.api import BaseObserver @@ -64,7 +64,7 @@ else: FileSystemEventHandler = object # dummy if TYPE_CHECKING: # this isn't ever used, but this will make type checking happy - from watchdog.events import FileCreatedEvent + from watchdog.events import FileSystemEvent from watchdog.observers import Observer from watchdog.observers.api import BaseObserver @@ -350,7 +350,7 @@ class EDLogs(FileSystemEventHandler): """ return bool(self.thread and self.thread.is_alive()) - def on_created(self, event: 'FileCreatedEvent') -> None: + def on_created(self, event: 'FileSystemEvent') -> None: """Watchdog callback when, e.g. client (re)started.""" if not event.is_directory and self._RE_LOGFILE.search(basename(event.src_path)): diff --git a/requirements.txt b/requirements.txt index 75ea4041..2e0fb39f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,7 +4,7 @@ pillow==10.3.0 # requests depends on this now ? charset-normalizer==3.3.2 -watchdog==3.0.0 +watchdog==4.0.0 # Commented out because this doesn't package well with py2exe infi.systray==0.1.12; sys_platform == 'win32' # argh==0.26.2 watchdog dep From 8198d779c3e7479bfc75dfae6faa47a25dc9a3ca Mon Sep 17 00:00:00 2001 From: David Sangrey Date: Thu, 2 May 2024 21:34:58 -0400 Subject: [PATCH 08/10] [830] Open Log Folder Natively --- EDMarketConnector.py | 6 +++--- prefs.py | 24 ++++++++++++++++-------- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/EDMarketConnector.py b/EDMarketConnector.py index 3ab97eb5..1ce34628 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -18,6 +18,7 @@ import subprocess import sys import threading import webbrowser +import tempfile from os import chdir, environ, path from time import localtime, strftime, time from typing import TYPE_CHECKING, Any, Literal @@ -47,8 +48,6 @@ if __name__ == '__main__': # output until after this redirect is done, if needed. if getattr(sys, 'frozen', False): # By default py2exe tries to write log to dirname(sys.executable) which fails when installed - import tempfile - # unbuffered not allowed for text in python3, so use `1 for line buffering log_file_path = path.join(tempfile.gettempdir(), f'{appname}.log') sys.stdout = sys.stderr = open(log_file_path, mode='wt', buffering=1) # Do NOT use WITH here. @@ -651,7 +650,8 @@ class AppWindow: self.help_menu.add_command(command=lambda: self.updater.check_for_updates()) # Check for Updates... # About E:D Market Connector self.help_menu.add_command(command=lambda: not self.HelpAbout.showing and self.HelpAbout(self.w)) - self.help_menu.add_command(command=prefs.help_open_log_folder) # Open Log Folder + logfile_loc = pathlib.Path(tempfile.gettempdir()) / appname + self.help_menu.add_command(command=lambda: prefs.open_folder(logfile_loc)) # Open Log Folder self.menubar.add_cascade(menu=self.help_menu) if sys.platform == 'win32': diff --git a/prefs.py b/prefs.py index 285ef0d7..81885257 100644 --- a/prefs.py +++ b/prefs.py @@ -8,14 +8,12 @@ import pathlib import sys import tempfile import tkinter as tk -import webbrowser from os import system from os.path import expanduser, expandvars, join, normpath from tkinter import colorchooser as tkColorChooser # type: ignore # noqa: N812 from tkinter import ttk from types import TracebackType from typing import TYPE_CHECKING, Any, Callable, Optional, Type - import myNotebook as nb # noqa: N813 import plug from config import appversion_nobuild, config @@ -44,14 +42,21 @@ if TYPE_CHECKING: def help_open_log_folder() -> None: """Open the folder logs are stored in.""" - logfile_loc = pathlib.Path(tempfile.gettempdir()) - logfile_loc /= f'{appname}' + logger.warning( + DeprecationWarning("This function is deprecated, use open_log_folder instead. " + "This function will be removed in 6.0 or later") + ) + open_folder(pathlib.Path(tempfile.gettempdir()) / appname) + + +def open_folder(file: pathlib.Path) -> None: + """Open the given file in the OS file explorer.""" if sys.platform.startswith('win'): # On Windows, use the "start" command to open the folder - system(f'start "" "{logfile_loc}"') + system(f'start "" "{file}"') elif sys.platform.startswith('linux'): # On Linux, use the "xdg-open" command to open the folder - system(f'xdg-open "{logfile_loc}"') + system(f'xdg-open "{file}"') class PrefsVersion: @@ -300,6 +305,9 @@ class PreferencesDialog(tk.Toplevel): ): self.geometry(f"+{position.left}+{position.top}") + # Set Log Directory + self.logfile_loc = pathlib.Path(tempfile.gettempdir()) / appname + def __setup_output_tab(self, root_notebook: ttk.Notebook) -> None: output_frame = nb.Frame(root_notebook) output_frame.columnconfigure(0, weight=1) @@ -625,7 +633,7 @@ class PreferencesDialog(tk.Toplevel): config_frame, # LANG: Label on button used to open a filesystem folder text=_('Open Log Folder'), # Button that opens a folder in Explorer/Finder - command=lambda: help_open_log_folder() + command=lambda: open_folder(self.logfile_loc) ).grid(column=2, padx=self.PADX, pady=0, sticky=tk.NSEW, row=cur_row) # Big spacer @@ -884,7 +892,7 @@ class PreferencesDialog(tk.Toplevel): plugins_frame, # LANG: Label on button used to open a filesystem folder text=_('Open'), # Button that opens a folder in Explorer/Finder - command=lambda: webbrowser.open(f'file:///{config.plugin_dir_path}') + command=lambda: open_folder(config.plugin_dir_path) ).grid(column=1, padx=self.PADX, pady=self.PADY, sticky=tk.N, row=cur_row) enabled_plugins = list(filter(lambda x: x.folder and x.module, plug.PLUGINS)) From 64cd5b3cc5ad8e2463b1da121f1e2f0107972dca Mon Sep 17 00:00:00 2001 From: Phoebe <40956085+C1701D@users.noreply.github.com> Date: Tue, 14 May 2024 01:42:26 +0200 Subject: [PATCH 09/10] [1173] Add alt_URL check --- ttkHyperlinkLabel.py | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/ttkHyperlinkLabel.py b/ttkHyperlinkLabel.py index 3bb878a6..f7780566 100644 --- a/ttkHyperlinkLabel.py +++ b/ttkHyperlinkLabel.py @@ -19,6 +19,7 @@ In addition to standard ttk.Label arguments, takes the following arguments: May be imported by plugins """ from __future__ import annotations +import html from functools import partial import sys import tkinter as tk @@ -27,9 +28,11 @@ from tkinter import font as tk_font from tkinter import ttk from typing import Any import plug +from os import path from config import config, logger from l10n import translations as tr from monitor import monitor +from EDMarketConnector import SHIPYARD_HTML_TEMPLATE class HyperlinkLabel(tk.Label or ttk.Label): # type: ignore @@ -70,7 +73,7 @@ class HyperlinkLabel(tk.Label or ttk.Label): # type: ignore # Add Menu Options self.plug_options = kw.pop('plug_options', None) self.name = kw.get('name', None) - if self.name == 'ship' and not bool(config.get_int("use_alt_shipyard_open")): + if self.name == 'ship': self.menu.add_separator() for url in plug.provides('shipyard_url'): self.menu.add_command( @@ -96,12 +99,27 @@ class HyperlinkLabel(tk.Label or ttk.Label): # type: ignore def open_shipyard(self, url: str): """Open the Current Ship Loadout in the Selected Provider.""" - if loadout := monitor.ship(): + if not (loadout := monitor.ship()): + logger.warning('No ship loadout, aborting.') + return '' + if not bool(config.get_int("use_alt_shipyard_open")): opener = plug.invoke(url, 'EDSY', 'shipyard_url', loadout, monitor.is_beta) if opener: return webbrowser.open(opener) - logger.warning('No ship loadout, aborting.') - return '' + else: + # Avoid file length limits if possible + provider = config.get_str('shipyard_provider', default='EDSY') + target = plug.invoke(provider, 'EDSY', 'shipyard_url', loadout, monitor.is_beta) + file_name = path.join(config.app_dir_path, "last_shipyard.html") + + with open(file_name, 'w') as f: + f.write(SHIPYARD_HTML_TEMPLATE.format( + link=html.escape(str(target)), + provider_name=html.escape(str(provider)), + ship_name=html.escape("Ship") + )) + + webbrowser.open(f'file://localhost/{file_name}') def open_system(self, url: str): """Open the Current System in the Selected Provider.""" From 459881d618ee04cfcfc2875139570c3bd1f86de6 Mon Sep 17 00:00:00 2001 From: David Sangrey Date: Mon, 13 May 2024 19:45:53 -0400 Subject: [PATCH 10/10] [1173] Fix Circular Import --- EDMarketConnector.py | 17 +---------------- ttkHyperlinkLabel.py | 16 +++++++++++++++- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/EDMarketConnector.py b/EDMarketConnector.py index d9243063..8eebd631 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -431,25 +431,10 @@ from hotkey import hotkeymgr from l10n import translations as tr from monitor import monitor from theme import theme -from ttkHyperlinkLabel import HyperlinkLabel +from ttkHyperlinkLabel import HyperlinkLabel, SHIPYARD_HTML_TEMPLATE SERVER_RETRY = 5 # retry pause for Companion servers [s] -SHIPYARD_HTML_TEMPLATE = """ - - - - - Redirecting you to your {ship_name} at {provider_name}... - - - - You should be redirected to your {ship_name} at {provider_name} shortly... - - - -""" - class AppWindow: """Define the main application window.""" diff --git a/ttkHyperlinkLabel.py b/ttkHyperlinkLabel.py index f7780566..3ec0a26d 100644 --- a/ttkHyperlinkLabel.py +++ b/ttkHyperlinkLabel.py @@ -32,7 +32,21 @@ from os import path from config import config, logger from l10n import translations as tr from monitor import monitor -from EDMarketConnector import SHIPYARD_HTML_TEMPLATE + +SHIPYARD_HTML_TEMPLATE = """ + + + + + Redirecting you to your {ship_name} at {provider_name}... + + + + You should be redirected to your {ship_name} at {provider_name} shortly... + + + +""" class HyperlinkLabel(tk.Label or ttk.Label): # type: ignore