Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UI rewrite in wxPython #2239

Closed
wants to merge 12 commits into from
3 changes: 0 additions & 3 deletions EDMC.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ def _(x: str): return x
import commodity
import companion
import edshipyard
import l10n
import loadout
import outfitting
import shipyard
Expand Down Expand Up @@ -66,8 +65,6 @@ def log_locale(prefix: str) -> None:
)


l10n.Translations.install_dummy()

SERVER_RETRY = 5 # retry pause for Companion servers [s]
EXIT_SUCCESS, EXIT_SERVER, EXIT_CREDENTIALS, EXIT_VERIFICATION, EXIT_LAGGING, EXIT_SYS_ERR, EXIT_ARGS, \
EXIT_JOURNAL_READ_ERR, EXIT_COMMANDER_UNKNOWN = range(9)
Expand Down
1,125 changes: 394 additions & 731 deletions EDMarketConnector.py

Large diffs are not rendered by default.

38 changes: 19 additions & 19 deletions companion.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@
import sys
import threading
import time
import tkinter as tk
import urllib.parse
import webbrowser
import wx
from email.utils import parsedate
from queue import Queue
from typing import TYPE_CHECKING, Any, Mapping, TypeVar
Expand All @@ -34,7 +34,7 @@
import killswitch
import protocol
from config import config, user_agent
from edmc_data import companion_category_map as category_map
from edmc_data import CapiResponseEvent, companion_category_map as category_map
from EDMCLogging import get_main_logger
from monitor import monitor

Expand Down Expand Up @@ -559,10 +559,10 @@ class EDMCCAPIReturn:
"""Base class for Request, Failure or Response."""

def __init__(
self, query_time: int, tk_response_event: str | None = None,
self, query_time: int, response_event: str | None = None,
play_sound: bool = False, auto_update: bool = False
):
self.tk_response_event = tk_response_event # Name of tk event to generate when response queued.
self.response_event = response_event # Name of wx event to generate when response queued.
self.query_time: int = query_time # When this query is considered to have started (time_t).
self.play_sound: bool = play_sound # Whether to play good/bad sounds for success/failure.
self.auto_update: bool = auto_update # Whether this was automatically triggered.
Expand All @@ -576,11 +576,11 @@ class EDMCCAPIRequest(EDMCCAPIReturn):
def __init__(
self, capi_host: str, endpoint: str,
query_time: int,
tk_response_event: str | None = None,
response_event: str | None = None,
play_sound: bool = False, auto_update: bool = False
):
super().__init__(
query_time=query_time, tk_response_event=tk_response_event,
query_time=query_time, response_event=response_event,
play_sound=play_sound, auto_update=auto_update
)
self.capi_host: str = capi_host # The CAPI host to use.
Expand Down Expand Up @@ -631,7 +631,7 @@ def __init__(self) -> None:
self.requests_session = requests.Session()
self.auth: Auth | None = None
self.retrying = False # Avoid infinite loop when successful auth / unsuccessful query
self.tk_master: tk.Tk | None = None
self.wx_master: wx.App | None = None

self.capi_raw_data = CAPIDataRaw() # Cache of raw replies from CAPI service
# Queue that holds requests for CAPI queries, the items should always
Expand All @@ -651,9 +651,9 @@ def __init__(self) -> None:
self.capi_query_thread.start()
logger.debug('Done')

def set_tk_master(self, master: tk.Tk) -> None:
"""Set a reference to main UI Tk root window."""
self.tk_master = master
def set_wx_master(self, master: wx.App) -> None:
"""Set a reference to main UI wx root window."""
self.wx_master = master

######################################################################
# Frontier Authorization
Expand Down Expand Up @@ -1013,10 +1013,10 @@ def capi_station_queries( # noqa: CCR001

# If the query came from EDMC.(py|exe) there's no tk to send an
# event too, so assume it will be polling the response queue.
if query.tk_response_event is not None:
if query.response_event is not None:
logger.trace_if('capi.worker', 'Sending <<CAPIResponse>>')
if self.tk_master is not None:
self.tk_master.event_generate('<<CAPIResponse>>')
if self.wx_master is not None:
wx.PostEvent(self.wx_master, CapiResponseEvent())

logger.info('CAPI worker thread DONE')

Expand All @@ -1031,14 +1031,14 @@ def capi_query_close_worker(self) -> None:
)

def station(
self, query_time: int, tk_response_event: str | None = None,
self, query_time: int, response_event: str | None = None,
play_sound: bool = False, auto_update: bool = False
) -> None:
"""
Perform CAPI quer(y|ies) for station data.

:param query_time: When this query was initiated.
:param tk_response_event: Name of tk event to generate when response queued.
:param response_event: Name of tk event to generate when response queued.
:param play_sound: Whether the app should play a sound on error.
:param auto_update: Whether this request was triggered automatically.
"""
Expand All @@ -1052,22 +1052,22 @@ def station(
EDMCCAPIRequest(
capi_host=capi_host,
endpoint=self._CAPI_PATH_STATION,
tk_response_event=tk_response_event,
response_event=response_event,
query_time=query_time,
play_sound=play_sound,
auto_update=auto_update
)
)

def fleetcarrier(
self, query_time: int, tk_response_event: str | None = None,
self, query_time: int, response_event: str | None = None,
play_sound: bool = False, auto_update: bool = False
) -> None:
"""
Perform CAPI query for fleetcarrier data.

:param query_time: When this query was initiated.
:param tk_response_event: Name of tk event to generate when response queued.
:param response_event: Name of tk event to generate when response queued.
:param play_sound: Whether the app should play a sound on error.
:param auto_update: Whether this request was triggered automatically.
"""
Expand All @@ -1081,7 +1081,7 @@ def fleetcarrier(
EDMCCAPIRequest(
capi_host=capi_host,
endpoint=self.FRONTIER_CAPI_PATH_FLEETCARRIER,
tk_response_event=tk_response_event,
response_event=response_event,
query_time=query_time,
play_sound=play_sound,
auto_update=auto_update
Expand Down
17 changes: 10 additions & 7 deletions dashboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@
import json
import sys
import time
import tkinter as tk
from calendar import timegm
from os.path import getsize, isdir, isfile, join
from typing import Any, cast
from typing import TYPE_CHECKING, Any, cast
from watchdog.observers.api import BaseObserver
from config import config
from edmc_data import DashboardEvent
from EDMCLogging import get_main_logger

logger = get_main_logger()
Expand All @@ -28,6 +28,9 @@
class FileSystemEventHandler: # type: ignore
"""Dummy class to represent a file system event handler on platforms other than Windows."""

if TYPE_CHECKING:
import wx


class Dashboard(FileSystemEventHandler):
"""Status.json handler."""
Expand All @@ -37,13 +40,13 @@ class Dashboard(FileSystemEventHandler):
def __init__(self) -> None:
FileSystemEventHandler.__init__(self) # futureproofing - not need for current version of watchdog
self.session_start: int = int(time.time())
self.root: tk.Tk = None # type: ignore
self.root: wx.App = None # type: ignore
self.currentdir: str = None # type: ignore # The actual logdir that we're monitoring
self.observer: Observer | None = None # type: ignore
self.observed = None # a watchdog ObservedWatch, or None if polling
self.status: dict[str, Any] = {} # Current status for communicating status back to main thread

def start(self, root: tk.Tk, started: int) -> bool:
def start(self, root: wx.App, started: int) -> bool:
"""
Start monitoring of Journal directory.

Expand Down Expand Up @@ -96,7 +99,7 @@ def start(self, root: tk.Tk, started: int) -> bool:
# data and to check whether the watchdog thread has crashed due to events not
# being supported on this filesystem.
logger.debug('Polling once to process pre-existing data, and check whether watchdog thread crashed...')
self.root.after(int(self._POLL * 1000/2), self.poll, True)
wx.CallLater(int(self._POLL * 1000/2), self.poll, True)
logger.debug('Done.')

return True
Expand Down Expand Up @@ -156,7 +159,7 @@ def poll(self, first_time: bool = False) -> None:
if emitter and emitter.is_alive(): # type: ignore
return # Watchdog thread still running - stop polling

self.root.after(self._POLL * 1000, self.poll) # keep polling
wx.CallLater(self._POLL * 1000, self.poll) # keep polling

def on_modified(self, event) -> None:
"""
Expand Down Expand Up @@ -186,7 +189,7 @@ def process(self, logfile: str | None = None) -> None:
entry_timestamp = timegm(time.strptime(entry['timestamp'], '%Y-%m-%dT%H:%M:%SZ'))
if entry_timestamp >= self.session_start and self.status != entry:
self.status = entry
self.root.event_generate('<<DashboardEvent>>', when="tail")
wx.PostEvent(self.root, DashboardEvent())
except Exception:
logger.exception('Processing Status.json')

Expand Down
35 changes: 35 additions & 0 deletions edmc_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
For easy reference any variable should be prefixed with the name of the file it
was either in originally, or where the primary code utilising it is.
"""
import wx.lib.newevent

# Map numeric 'demand/supply brackets' to the names as shown in-game.
commodity_bracketmap = {
Expand Down Expand Up @@ -591,6 +592,40 @@
},
}

edmc_wx_languages = {
None: wx.LANGUAGE_DEFAULT,
'cs': wx.LANGUAGE_CZECH,
'de': wx.LANGUAGE_GERMAN,
'en': wx.LANGUAGE_ENGLISH,
'es': wx.LANGUAGE_SPANISH,
'fi': wx.LANGUAGE_FINNISH,
'fr': wx.LANGUAGE_FRENCH,
'hu': wx.LANGUAGE_HUNGARIAN,
'it': wx.LANGUAGE_ITALIAN,
'ja': wx.LANGUAGE_JAPANESE,
'ko': wx.LANGUAGE_KOREAN,
'lv': wx.LANGUAGE_LATVIAN,
'nl': wx.LANGUAGE_DUTCH,
'pl': wx.LANGUAGE_POLISH,
'pt-BR': wx.LANGUAGE_PORTUGUESE_BRAZILIAN,
'pt-PT': wx.LANGUAGE_PORTUGUESE_PORTUGAL,
'ru': wx.LANGUAGE_RUSSIAN,
'sl': wx.LANGUAGE_SLOVENIAN,
'sr-Latn': wx.LANGUAGE_SERBIAN_LATIN,
'sr-Latn-BA': wx.LANGUAGE_SERBIAN_LATIN_BOSNIA_AND_HERZEGOVINA,
'sv-SE': wx.LANGUAGE_SWEDISH_SWEDEN,
'tr': wx.LANGUAGE_TURKISH,
'uk': wx.LANGUAGE_UKRAINIAN,
'zh-Hans': wx.LANGUAGE_CHINESE_SIMPLIFIED_EXPLICIT,
}

CapiAuthEvent, EVT_CAPI_AUTH = wx.lib.newevent.NewEvent()
CapiRequestEvent, EVT_CAPI_REQUEST = wx.lib.newevent.NewEvent()
CapiResponseEvent, EVT_CAPI_RESPONSE = wx.lib.newevent.NewEvent()
JournalQueueEvent, EVT_JOURNAL_QUEUE = wx.lib.newevent.NewEvent()
DashboardEvent, EVT_DASHBOARD = wx.lib.newevent.NewEvent()
PluginErrorEvent, EVT_PLUGIN_ERROR = wx.lib.newevent.NewEvent()

# WORKAROUND 2021-07-03 | 4.0.0.600 Update 5: duplicates of `fileheader` keys in `LoadGame`,
# but the GameLanguage in the latter has doubled up the `\`, so cater for either here.
# This is sourced from what the game is passed by the launcher, caveat emptor. It was mentioned that / is also
Expand Down
1 change: 0 additions & 1 deletion hotkey/windows.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
import pathlib
import sys
import threading
import tkinter as tk
import winsound
from ctypes.wintypes import DWORD, HWND, LONG, LPWSTR, MSG, ULONG, WORD
from config import config
Expand Down
Binary file added img/edsm_error.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/edsm_known.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/edsm_new.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added img/edsm_unknown.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading