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

Inform plugins of Cmdr and Beta status

Notify plugins when Cmdr or Beta status changes while the preferences dialog
is open.

Display a note on the Credentials tab when Cmdr is not set. Addresses #224
This commit is contained in:
Jonathan Harris 2017-07-27 18:29:02 +01:00
parent 4e61ffb92d
commit 60ad3b4c09
6 changed files with 134 additions and 51 deletions

View File

@ -476,7 +476,11 @@ class AppWindow:
self.edit_menu.entryconfigure(0, state=tk.NORMAL) # Copy
# stuff we can do when not docked
self.status['text'] = plug.notify_newdata(data) or ''
err = plug.notify_newdata(data, monitor.is_beta)
self.status['text'] = err and err or ''
if err:
play_bad = True
if config.getint('output') & config.OUT_SHIP:
loadout.export(data)
@ -717,9 +721,11 @@ class AppWindow:
return # Startup or in CQC
# Plugins
err = plug.notify_journal_entry(monitor.cmdr, monitor.system, monitor.station, entry, monitor.state)
err = plug.notify_journal_entry(monitor.cmdr, monitor.is_beta, monitor.system, monitor.station, entry, monitor.state)
if err:
self.status['text'] = err
if not config.getint('hotkey_mute'):
hotkeymgr.play_bad()
if entry['event'] in ['StartUp', 'LoadGame'] and monitor.started:
# Can start interaction monitoring
@ -800,9 +806,11 @@ class AppWindow:
return
# Currently we don't do anything with these events
err = plug.notify_interaction(monitor.cmdr, entry)
err = plug.notify_interaction(monitor.cmdr, monitor.is_beta, entry)
if err:
self.status['text'] = err
if not config.getint('hotkey_mute'):
hotkeymgr.play_bad()
def edsmpoll(self):
result = self.edsm.result

View File

@ -301,6 +301,9 @@
/* Dark theme color setting. [prefs.py] */
"Normal text" = "Normal text";
/* Displayed when credentials settings are greyed out. [prefs.py] */
"Not available while E:D is at the main menu" = "Not available while E:D is at the main menu";
/* Combat rank. [stats.py] */
"Novice" = "Novice";

View File

@ -41,14 +41,14 @@ You can use `set()`, `get()` and `getint()` from EDMC's config object to retriev
Use `numberFromString()` from EDMC's Locale object to parse input numbers in a locale-independent way.
```
```python
import Tkinter as tk
import myNotebook as nb
from config import config
this = sys.modules[__name__] # For holding module globals
def plugin_prefs(parent):
def plugin_prefs(parent, cmdr, is_beta):
"""
Return a TK Frame for adding to the EDMC settings dialog.
"""
@ -63,8 +63,8 @@ def plugin_prefs(parent):
This gets called when the user dismisses the settings dialog:
```
def prefs_changed():
```python
def prefs_changed(cmdr, is_beta):
"""
Save settings.
"""
@ -77,7 +77,7 @@ You can also have your plugin add an item to the EDMC main window and update it
You can use `stringFromNumber()` from EDMC's Locale object to format numbers in a locale-independent way.
```
```python
this = sys.modules[__name__] # For holding module globals
def plugin_app(parent):
@ -104,8 +104,8 @@ This gets called when EDMC sees a new entry in the game's journal. `state` is a
A special 'StartUp' entry is sent if EDMC is started while the game is already running. In this case you won't receive initial events such as "LoadGame", "Rank", "Location", etc. However the `state` dictionary will reflect the cumulative effect of these missed events.
```
def journal_entry(cmdr, system, station, entry, state):
```python
def journal_entry(cmdr, is_beta, system, station, entry, state):
if entry['event'] == 'FSDJump':
# We arrived at a new system!
if 'StarPos' in entry:
@ -120,8 +120,8 @@ This gets called when the player interacts with another Cmdr in-game.
If EDMC is started while the game is already running EDMC will send the last few interaction events from the current game session.
```
def interaction(cmdr, entry):
```python
def interaction(cmdr, is_beta, entry):
# Log type of interaction, Cmdr name, and local time
sys.stderr.write("{} Cmdr {} at {}\n".format(', '.join(entry['Interactions']),
entry['Name'].encode('utf-8'),
@ -133,8 +133,8 @@ def interaction(cmdr, entry):
This gets called when EDMC has just fetched fresh Cmdr and station data from Frontier's servers.
```
def cmdr_data(data):
```python
def cmdr_data(data, is_beta):
"""
We have new data on our commander
"""

101
plug.py
View File

@ -8,8 +8,12 @@ import operator
import threading # We don't use it, but plugins might
from traceback import print_exc
import Tkinter as tk
import myNotebook as nb
from config import config, appname
# List of loaded Plugins
PLUGINS = []
@ -53,25 +57,42 @@ class Plugin(object):
:param parent: the parent frame for this entry.
:return:
"""
try:
plugin_app = self._get_func('plugin_app')
return plugin_app and plugin_app(parent)
except:
print_exc()
return None
plugin_app = self._get_func('plugin_app')
if plugin_app:
try:
appitem = plugin_app(parent)
if isinstance(appitem, tuple):
if len(appitem) != 2 or not isinstance(appitem[0], tk.Widget) or not isinstance(appitem[1], tk.Widget):
raise AssertionError
elif not isinstance(appitem, tk.Widget):
raise AssertionError
return appitem
except:
print_exc()
return None
def get_prefs(self, parent):
def get_prefs(self, parent, cmdr, is_beta):
"""
If the plugin provides a prefs frame, create and return it.
:param parent: the parent frame for this preference tab.
:param cmdr: current Cmdr name (or None). Relevant if you want to have
different settings for different user accounts.
:param is_beta: whether the player is in a Beta universe.
:return:
"""
try:
plugin_prefs = self._get_func('plugin_prefs')
return plugin_prefs and plugin_prefs(parent)
except:
print_exc()
return None
plugin_prefs = self._get_func('plugin_prefs')
if plugin_prefs:
try:
if plugin_prefs.func_code.co_argcount == 1:
frame = plugin_prefs(parent)
else:
frame = plugin_prefs(parent, cmdr, is_beta)
if not isinstance(frame, nb.Frame):
raise AssertionError
return frame
except:
print_exc()
return None
def load_plugins():
@ -109,28 +130,54 @@ def load_plugins():
imp.release_lock()
def notify_prefs_changed():
def notify_prefs_cmdr_changed(cmdr, is_beta):
"""
Notify each plugin that the Cmdr has been changed while the settings dialog is open.
Relevant if you want to have different settings for different user accounts.
:param cmdr: current Cmdr name (or None).
:param is_beta: whether the player is in a Beta universe.
:return:
"""
for plugin in PLUGINS:
prefs_cmdr_changed = plugin._get_func('prefs_cmdr_changed')
if prefs_cmdr_changed:
try:
prefs_cmdr_changed(cmdr, is_beta)
except:
print_exc()
def notify_prefs_changed(cmdr, is_beta):
"""
Notify each plugin that the settings dialog has been closed.
The prefs frame and any widgets you created in your `get_prefs()` callback
will be destroyed on return from this function, so take a copy of any
values that you want to save.
:param cmdr: current Cmdr name (or None).
:param is_beta: whether the player is in a Beta universe.
:return:
"""
for plugin in PLUGINS:
prefs_changed = plugin._get_func('prefs_changed')
if prefs_changed:
try:
prefs_changed()
if prefs_changed.func_code.co_argcount == 0:
prefs_changed()
else:
prefs_changed(cmdr, is_beta)
except:
print_exc()
def notify_journal_entry(cmdr, system, station, entry, cmdr_state):
def notify_journal_entry(cmdr, is_beta, system, station, entry, state):
"""
Send a journal entry to each plugin.
:param cmdr: The Cmdr name, or None if not yet known
:param system: The current system, or None if not yet known
:param station: The current station, or None if not docked or not yet known
:param entry: The journal entry as a dictionary
:param cmdr_state: A dictionary containing info about the Cmdr, current ship and cargo
:param state: A dictionary containing info about the Cmdr, current ship and cargo
:param is_beta: whether the player is in a Beta universe.
:return: Error message from the first plugin that returns one (if any)
"""
error = None
@ -141,18 +188,21 @@ def notify_journal_entry(cmdr, system, station, entry, cmdr_state):
# Pass a copy of the journal entry in case the callee modifies it
if journal_entry.func_code.co_argcount == 4:
error = error or journal_entry(cmdr, system, station, dict(entry))
elif journal_entry.func_code.co_argcount == 5:
error = error or journal_entry(cmdr, system, station, dict(entry), dict(state))
else:
error = error or journal_entry(cmdr, system, station, dict(entry), dict(cmdr_state))
error = error or journal_entry(cmdr, is_beta, system, station, dict(entry), dict(state))
except:
print_exc()
return error
def notify_interaction(cmdr, entry):
def notify_interaction(cmdr, is_beta, entry):
"""
Send an interaction entry to each plugin.
:param cmdr: The piloting Cmdr name
:param entry: The interaction entry as a dictionary
:param is_beta: whether the player is in a Beta universe.
:return: Error message from the first plugin that returns one (if any)
"""
error = None
@ -161,7 +211,10 @@ def notify_interaction(cmdr, entry):
if interaction:
try:
# Pass a copy of the interaction entry in case the callee modifies it
error = error or interaction(cmdr, dict(entry))
if interaction.func_code.co_argcount == 2:
error = error or interaction(cmdr, dict(entry))
else:
error = error or interaction(cmdr, is_beta, dict(entry))
except:
print_exc()
return error
@ -188,10 +241,11 @@ def notify_system_changed(timestamp, system, coordinates):
print_exc()
def notify_newdata(data):
def notify_newdata(data, is_beta):
"""
Send the latest EDMC data from the FD servers to each plugin
:param data:
:param is_beta: whether the player is in a Beta universe.
:return: Error message from the first plugin that returns one (if any)
"""
error = None
@ -199,7 +253,10 @@ def notify_newdata(data):
cmdr_data = plugin._get_func('cmdr_data')
if cmdr_data:
try:
error = error or cmdr_data(data)
if cmdr_data.func_code.co_argcount == 1:
error = error or cmdr_data(data)
else:
error = error or cmdr_data(data, is_beta)
except:
print_exc()
return error

View File

@ -57,12 +57,12 @@ def plugin_app(parent):
this.station = HyperlinkLabel(parent, url = station_url, popup_copy = lambda x: x != STATION_UNDOCKED)
return (this.station_label, this.station)
def prefs_changed():
def prefs_changed(cmdr, is_beta):
this.station_label['text'] = _('Station') + ':'
def journal_entry(cmdr, system, station, entry, state):
def journal_entry(cmdr, is_beta, system, station, entry, state):
this.system = system
this.station['text'] = station or (system_id(system) and STATION_UNDOCKED or '')
def cmdr_data(data):
def cmdr_data(data, is_beta):
this.station['text'] = data['commander']['docked'] and data['lastStarport']['name'] or (system_id(data['lastSystem']['name']) and STATION_UNDOCKED or '')

View File

@ -82,6 +82,8 @@ class PreferencesDialog(tk.Toplevel):
self.resizable(tk.FALSE, tk.FALSE)
self.cmdr = False # Note if Cmdr changes in the Journal
self.is_beta = False # Note if Beta status changes in the Journal
self.cmdrchanged_alarm = None
frame = ttk.Frame(self)
frame.grid(sticky=tk.NSEW)
@ -98,7 +100,7 @@ class PreferencesDialog(tk.Toplevel):
nb.Label(credframe, text=_('Credentials')).grid(padx=PADX, sticky=tk.W) # Section heading in settings
ttk.Separator(credframe, orient=tk.HORIZONTAL).grid(columnspan=2, padx=PADX, pady=PADY, sticky=tk.EW)
self.cred_label = nb.Label(credframe, text=_('Please log in with your Elite: Dangerous account details')) # Use same text as E:D Launcher's login dialog
self.cred_label = nb.Label(credframe)
self.cred_label.grid(padx=PADX, columnspan=2, sticky=tk.W)
self.cmdr_label = nb.Label(credframe, text=_('Cmdr')) # Main window
self.cmdr_label.grid(row=10, padx=PADX, sticky=tk.W)
@ -212,7 +214,7 @@ class PreferencesDialog(tk.Toplevel):
# build plugin prefs tabs
for plugin in plug.PLUGINS:
plugframe = plugin.get_prefs(notebook)
plugframe = plugin.get_prefs(notebook, monitor.cmdr, monitor.is_beta)
if plugframe:
notebook.add(plugframe, text=plugin.name)
@ -371,7 +373,7 @@ class PreferencesDialog(tk.Toplevel):
self.protocol("WM_DELETE_WINDOW", self._destroy)
# Selectively disable buttons depending on output settings
self.outvarchanged()
self.cmdrchanged()
self.themevarchanged()
# disable hotkey for the duration
@ -390,11 +392,16 @@ class PreferencesDialog(tk.Toplevel):
0x10000, None, position):
self.geometry("+%d+%d" % (position.left, position.top))
def outvarchanged(self, event=None):
self.cmdr_text['state'] = self.edsm_cmdr_text['state'] = tk.NORMAL # must be writable to update
self.cmdr_text['text'] = self.edsm_cmdr_text['text'] = (monitor.cmdr or _('None')) + (monitor.is_beta and ' [Beta]' or '') # No hotkey/shortcut currently defined
if self.cmdr != monitor.cmdr:
def cmdrchanged(self, event=None):
if self.cmdr != monitor.cmdr or self.is_beta != monitor.is_beta:
# Cmdr has changed - update settings
if monitor.cmdr:
self.cred_label['text'] = _('Please log in with your Elite: Dangerous account details') # Use same text as E:D Launcher's login dialog
else:
self.cred_label['text'] = _('Not available while E:D is at the main menu') # Displayed when credentials settings are greyed out
self.cmdr_label['state'] = self.username_label['state'] = self.password_label['state'] = self.cmdr_text['state'] = self.username['state'] = self.password['state'] = monitor.cmdr and tk.NORMAL or tk.DISABLED
self.cmdr_text['text'] = (monitor.cmdr or _('None')) + (monitor.is_beta and ' [Beta]' or '') # No hotkey/shortcut currently defined
self.username['state'] = tk.NORMAL
self.username.delete(0, tk.END)
self.password['state'] = tk.NORMAL
@ -415,18 +422,23 @@ class PreferencesDialog(tk.Toplevel):
self.password.insert(0, config.get('password') or '')
self.edsm_user.insert(0,config.get('edsm_cmdrname') or '')
self.edsm_apikey.insert(0, config.get('edsm_apikey') or '')
if self.cmdr is not False: # Don't notify on first run
plug.notify_prefs_cmdr_changed(monitor.cmdr, monitor.is_beta)
self.cmdr = monitor.cmdr
self.is_beta = monitor.is_beta
cmdr_state = monitor.cmdr and tk.NORMAL or tk.DISABLED
self.cred_label['state'] = self.cmdr_label['state'] = self.username_label['state'] = self.password_label['state'] = cmdr_state
self.cmdr_text['state'] = self.username['state'] = self.password['state'] = cmdr_state
# Poll
self.cmdrchanged_alarm = self.after(1000, self.cmdrchanged)
def outvarchanged(self, event=None):
self.displaypath(self.outdir, self.outdir_entry)
self.displaypath(self.logdir, self.logdir_entry)
self.displaypath(self.interactiondir, self.interactiondir_entry)
logdir = self.logdir.get()
logvalid = logdir and exists(logdir)
if not logvalid:
self.cred_label['text'] = 'Check %s' % _('E:D journal file location') # Location of the new Journal file in E:D 2.2
self.out_label['state'] = self.out_csv_button['state'] = self.out_td_button['state'] = self.out_ship_button['state'] = tk.NORMAL or tk.DISABLED
local = self.out_td.get() or self.out_csv.get() or self.out_ship.get()
@ -613,7 +625,7 @@ class PreferencesDialog(tk.Toplevel):
config.set('journaldir', logdir)
interactiondir = self.interactiondir.get()
if config.default_journal_dir and interactiondir.lower() == config.default_interaction_dir.lower():
if config.default_interaction_dir and interactiondir.lower() == config.default_interaction_dir.lower():
config.set('interactiondir', '') # default location
else:
config.set('interactiondir', interactiondir)
@ -637,13 +649,16 @@ class PreferencesDialog(tk.Toplevel):
config.set('anonymous', self.out_anon.get())
plug.notify_prefs_changed()
plug.notify_prefs_changed(monitor.cmdr, monitor.is_beta)
self._destroy()
if self.callback:
self.callback()
def _destroy(self):
if self.cmdrchanged_alarm is not None:
self.after_cancel(self.cmdrchanged_alarm)
self.cmdrchanged_alarm = None
self.parent.wm_attributes('-topmost', config.getint('always_ontop') and 1 or 0)
self.destroy()