diff --git a/EDMarketConnector.py b/EDMarketConnector.py index af7a2b665..747d50ce5 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -417,25 +417,10 @@ def already_running_popup(): 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.""" @@ -500,13 +485,13 @@ def open_window(systray: 'SysTrayIcon') -> None: 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: # @@ -1613,7 +1598,7 @@ def plugin_error(self, event=None) -> None: 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 '' @@ -1640,13 +1625,13 @@ def shipyard_url(self, shipname: str) -> str | None: 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 b2c46d7cf..38a7fbed6 100644 --- a/L10n/en.template +++ b/L10n/en.template @@ -788,3 +788,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/myNotebook.py b/myNotebook.py index 43acfebdf..8a3cf9010 100644 --- a/myNotebook.py +++ b/myNotebook.py @@ -121,7 +121,7 @@ def paste(self) -> None: 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 @@ def __init__(self, master: ttk.Frame | None = None, **kw): 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) diff --git a/ttkHyperlinkLabel.py b/ttkHyperlinkLabel.py index d026f619d..3ec0a26d7 100644 --- a/ttkHyperlinkLabel.py +++ b/ttkHyperlinkLabel.py @@ -19,14 +19,34 @@ May be imported by plugins """ from __future__ import annotations - +import html +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 os import path +from config import config, logger from l10n import translations as tr +from monitor import monitor + +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 @@ -64,6 +84,72 @@ def __init__(self, master: ttk.Frame | tk.Frame | None = None, **kw: Any) -> Non 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': + 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 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) + 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.""" + 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: