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

Poll logs for current system.

This commit is contained in:
Jonathan Harris 2015-10-31 01:25:18 +00:00
parent e50cd2b808
commit d485a73243
4 changed files with 367 additions and 29 deletions

View File

@ -30,6 +30,7 @@ import eddb
import prefs
from config import appname, applongname, config
from hotkey import hotkeymgr
from monitor import monitor
l10n.Translations().install()
EDDB = eddb.EDDB()
@ -169,6 +170,12 @@ class AppWindow:
self.w.bind_all('<<Invoke>>', self.getandsend) # user-generated
hotkeymgr.register(self.w, config.getint('hotkey_code'), config.getint('hotkey_mods'))
# Install log monitoring
monitor.set_callback(self.system_change)
if (config.getint('output') & config.OUT_LOG_AUTO) and (config.getint('output') & (config.OUT_LOG_AUTO|config.OUT_LOG_EDSM)):
monitor.enable_logging()
monitor.start()
# call after credentials have changed
def login(self):
self.status['text'] = _('Logging in...')
@ -362,6 +369,13 @@ class AppWindow:
except:
pass
def system_change(self, system, timestamp):
if self.system['text'] != system:
# TODO: EDSM lookup and csv and/or EDSM log
self.system['text'] = system
self.station['text'] = EDDB.system(system) and self.STATION_UNDOCKED or ''
self.status['text'] = strftime(_('Last updated at {HH}:{MM}:{SS}').format(HH='%H', MM='%M', SS='%S').encode('utf-8'), localtime(timestamp)).decode('utf-8')
def edsmpoll(self):
result = self.edsm.result
if result['done']:

View File

@ -74,6 +74,7 @@ class Config:
#OUT_STAT = 64 # No longer available
OUT_SHIP_CORIOLIS = 128
OUT_LOG_EDSM = 256
OUT_LOG_AUTO = 512
if platform=='darwin':

296
monitor.py Normal file
View File

@ -0,0 +1,296 @@
import re
import threading
from os import listdir, pardir, rename, unlink
from os.path import exists, isdir, isfile, join
from platform import machine
from sys import platform
from time import strptime, localtime, mktime, sleep, time
from datetime import datetime
if __debug__:
from traceback import print_exc
if platform=='darwin':
from AppKit import NSWorkspace
from Foundation import NSSearchPathForDirectoriesInDomains, NSApplicationSupportDirectory, NSUserDomainMask
elif platform=='win32':
import ctypes
CSIDL_LOCAL_APPDATA = 0x001C
CSIDL_PROGRAM_FILESX86 = 0x002A
# _winreg that ships with Python 2 doesn't support unicode, so do this instead
from ctypes.wintypes import *
HKEY_LOCAL_MACHINE = 0x80000002
KEY_READ = 0x00020019
REG_SZ = 1
RegOpenKeyEx = ctypes.windll.advapi32.RegOpenKeyExW
RegOpenKeyEx.restype = LONG
RegOpenKeyEx.argtypes = [HKEY, LPCWSTR, DWORD, DWORD, ctypes.POINTER(HKEY)]
RegCloseKey = ctypes.windll.advapi32.RegCloseKey
RegCloseKey.restype = LONG
RegCloseKey.argtypes = [HKEY]
RegQueryValueEx = ctypes.windll.advapi32.RegQueryValueExW
RegQueryValueEx.restype = LONG
RegQueryValueEx.argtypes = [HKEY, LPCWSTR, LPCVOID, ctypes.POINTER(DWORD), LPCVOID, ctypes.POINTER(DWORD)]
RegEnumKeyEx = ctypes.windll.advapi32.RegEnumKeyExW
RegEnumKeyEx.restype = LONG
RegEnumKeyEx.argtypes = [HKEY, DWORD, LPWSTR, ctypes.POINTER(DWORD), ctypes.POINTER(DWORD), LPWSTR, ctypes.POINTER(DWORD), ctypes.POINTER(FILETIME)]
WNDENUMPROC = ctypes.WINFUNCTYPE(BOOL, HWND, ctypes.POINTER(DWORD))
EnumWindows = ctypes.windll.user32.EnumWindows
EnumWindows.argtypes = [WNDENUMPROC, LPARAM]
GetWindowText = ctypes.windll.user32.GetWindowTextW
GetWindowText.argtypes = [HWND, LPWSTR, ctypes.c_int]
GetWindowTextLength = ctypes.windll.user32.GetWindowTextLengthW
@WNDENUMPROC
def EnumWindowsProc(hwnd, lParam):
l = GetWindowTextLength(hwnd) + 1
buf = ctypes.create_unicode_buffer(l)
if GetWindowText(hwnd, buf, l) and buf.value.startswith('Elite - Dangerous'):
lParam[0] = 1
return False # stop enumeration
return True
class EDLogs:
def __init__(self):
self.logdir = self._logdir()
self.logging_enabled = self._logging_enabled
self._restart_required = False
self.observer = None
self.callback = None
def set_callback(self, callback):
self.callback = callback
def enable_logging(self):
if self.logging_enabled():
return True
elif self._enable_logging():
self._restart_required = self._ED_is_running()
return True
else:
return False
def restart_required(self):
if not self._ED_is_running():
self._restart_required = False
return self._restart_required
def logging_enabled_in_file(self, appconf):
if not isfile(appconf):
return False
with open(appconf, 'rU') as f:
content = f.read().lower()
start = content.find('<network')
end = content.find('</network>')
if start >= 0 and end >= 0:
return bool(re.search('verboselogging\s*=\s*\"1\"', content[start+8:end]))
else:
return False
def enable_logging_in_file(self, appconf):
try:
if not exists(appconf):
with open(appconf, 'wt') as f:
f.write('<AppConfig>\n\t<Network\n\t\tVerboseLogging="1"\n\t>\n\t</Network>\n</AppConfig>\n')
return True
with open(appconf, 'rU') as f:
content = f.read()
f.close()
backup = appconf[:-4] + '_backup.xml'
if exists(backup):
unlink(backup)
rename(appconf, backup)
with open(appconf, 'wt') as f:
start = content.lower().find('<network')
if start >= 0:
f.write(content[:start+8] + '\n\t\tVerboseLogging="1"' + content[start+8:])
else:
start = content.lower().find("</appconfig>")
if start >= 0:
f.write(content[:start] + '\t<Network\n\t\tVerboseLogging="1"\n\t>\n\t</Network>\n' + content[start:])
else:
f.write(content) # eh ?
return False
assert self._logging_enabled()
return self.logging_enabled_in_file(appconf)
except:
if __debug__: print_exc()
return False
def start(self):
self.stop()
if not self.logdir or not self.callback:
return False
self.observer = threading.Thread(target = self.worker, name = 'netLog worker')
self.observer.daemon = True
self.observer.start()
def stop(self):
if self.observer:
self.observer.stop()
self.observer = None
def worker(self):
regexp = re.compile('{(.+)} System:[^\(]*\(([^\)]+)')
# Seek to the end of the latest log file
logfiles = sorted([x for x in listdir(self.logdir) if x.startswith('netLog.')])
logfile = logfiles and logfiles[-1] or None
if logfile:
loghandle = open(join(self.logdir, logfile), 'rt')
loghandle.seek(0, 2) # seek to EOF
else:
loghandle = None
while True:
# Check whether new log file started, e.g. client restarted. Assumes logs sort alphabetically.
logfiles = sorted([x for x in listdir(self.logdir) if x.startswith('netLog.')])
newlogfile = logfiles and logfiles[-1] or None
if logfile != newlogfile:
logfile = newlogfile
if loghandle:
loghandle.close()
loghandle = open(join(self.logdir, logfile), 'rt')
if logfile:
system = visited = None
loghandle.seek(0, 1) # reset EOF flag
for line in loghandle:
match = regexp.match(line)
if match:
system, visited = match.group(2), match.group(1)
if system:
self._restart_required = False # clearly logging is working
# Convert local time string to UTC date and time
visited_struct = strptime(visited, '%H:%M:%S')
now = localtime()
if now.tm_hour == 0 and visited_struct.tm_hour == 23:
# Crossed midnight between timestamp and poll
now = localtime(time()-60)
datetime_struct = datetime(now.tm_year, now.tm_mon, now.tm_mday, visited_struct.tm_hour, visited_struct.tm_min, visited_struct.tm_sec).timetuple() # still local time
self.callback(system, mktime(datetime_struct))
sleep(10) # New system gets posted to log file before hyperspace ends, so don't need to poll too often
if platform=='darwin':
def _logdir(self):
# https://support.frontier.co.uk/kb/faq.php?id=97
suffix = join('Frontier Developments', 'Elite Dangerous')
paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, True)
if len(paths) and isdir(paths[0]) and isfile(join(paths[0], suffix, 'AppNetCfg.xml')) and isdir(join(paths[0], suffix, 'Logs')):
return join(paths[0], suffix, 'Logs')
else:
return None
def _logging_enabled(self):
return self.logdir and self.logging_enabled_in_file(join(self.logdir, pardir, 'AppConfigLocal.xml'))
def _enable_logging(self):
return self.logdir and self.enable_logging_in_file(join(self.logdir, pardir, 'AppConfigLocal.xml'))
def _ED_is_running(self):
for x in NSWorkspace.sharedWorkspace().runningApplications():
if x.bundleIdentifier() == 'uk.co.frontier.EliteDangerous':
return True
else:
return False
elif platform=='win32':
def _logdir(self):
# First try under the Launcher
key = HKEY()
if not RegOpenKeyEx(HKEY_LOCAL_MACHINE,
machine().endswith('64') and
r'SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall' or # Assumes that the launcher is a 32bit process
r'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall',
0, KEY_READ, ctypes.byref(key)):
buf = ctypes.create_unicode_buffer(MAX_PATH)
i = 0
while True:
size = DWORD(MAX_PATH)
if RegEnumKeyEx(key, i, buf, ctypes.byref(size), None, None, None, None):
break
subkey = HKEY()
if not RegOpenKeyEx(key, buf, 0, KEY_READ, ctypes.byref(subkey)):
valtype = DWORD()
valsize = DWORD((len('Frontier Developments')+1)*2)
valbuf = ctypes.create_unicode_buffer(valsize.value / 2)
if not RegQueryValueEx(subkey, 'Publisher', 0, ctypes.byref(valtype), valbuf, ctypes.byref(valsize)) and valtype.value == REG_SZ and valbuf.value == 'Frontier Developments':
if not RegQueryValueEx(subkey, 'InstallLocation', 0, ctypes.byref(valtype), None, ctypes.byref(valsize)) and valtype.value == REG_SZ:
valbuf = ctypes.create_unicode_buffer(valsize.value / 2)
if not RegQueryValueEx(subkey, 'InstallLocation', 0, ctypes.byref(valtype), valbuf, ctypes.byref(valsize)):
custpath = join(valbuf.value, 'Products')
if isdir(custpath):
for d in listdir(custpath):
if d.startswith('FORC-FDEV-D-1') and isfile(join(custpath, d, 'AppConfig.xml')) and isdir(join(custpath, d, 'Logs')):
RegCloseKey(subkey)
RegCloseKey(key)
return join(custpath, d, 'Logs')
RegCloseKey(subkey)
i += 1
RegCloseKey(key)
# https://support.elitedangerous.com/kb/faq.php?id=108
programs = ctypes.create_unicode_buffer(MAX_PATH)
ctypes.windll.shell32.SHGetSpecialFolderPathW(0, programs, CSIDL_PROGRAM_FILESX86, 0)
applocal = ctypes.create_unicode_buffer(MAX_PATH)
ctypes.windll.shell32.SHGetSpecialFolderPathW(0, applocal, CSIDL_LOCAL_APPDATA, 0)
for base in [join(programs.value, 'Steam', 'steamapps', 'common', 'Elite Dangerous', 'Products'),
join(programs.value, 'Frontier', 'Products'),
join(applocal.value, 'Frontier_Developments', 'Products')]:
if isdir(base):
for d in listdir(base):
if d.startswith('FORC-FDEV-D-1') and isfile(join(base, d, 'AppConfig.xml')) and isdir(join(base, d, 'Logs')):
return join(base, d, 'Logs')
return None
def _logging_enabled(self):
return self.logdir and (self.logging_enabled_in_file(join(self.logdir, pardir, 'AppConfigLocal.xml')) or
self.logging_enabled_in_file(join(self.logdir, pardir, 'AppConfig.xml')))
def _enable_logging(self):
return self.logdir and self.enable_logging_in_file(isfile(join(self.logdir, pardir, 'AppConfigLocal.xml')) and join(self.logdir, pardir, 'AppConfigLocal.xml') or join(self.logdir, pardir, 'AppConfig.xml'))
def _ED_is_running(self):
retval = DWORD(0)
EnumWindows(EnumWindowsProc, ctypes.addressof(retval))
return bool(retval)
elif platform=='linux2':
def _logdir(self):
return None
def _logging_enabled(self):
return False
def _enable_logging(self):
return False
def _ED_is_running(self):
return False
# singleton
monitor = EDLogs()

View File

@ -11,6 +11,7 @@ from ttkHyperlinkLabel import HyperlinkLabel
from config import applongname, config
from hotkey import hotkeymgr
from monitor import monitor
if platform == 'darwin':
@ -71,7 +72,7 @@ class PreferencesDialog(tk.Toplevel):
frame.grid(sticky=tk.NSEW)
credframe = ttk.LabelFrame(frame, text=_('Credentials')) # Section heading in settings
credframe.grid(padx=10, pady=10, sticky=tk.NSEW)
credframe.grid(padx=10, pady=5, sticky=tk.NSEW)
credframe.columnconfigure(1, weight=1)
ttk.Label(credframe, text=_('Please log in with your Elite: Dangerous account details')).grid(row=0, columnspan=2, sticky=tk.W) # Use same text as E:D Launcher's login dialog
@ -90,30 +91,35 @@ class PreferencesDialog(tk.Toplevel):
child.grid_configure(padx=5, pady=3)
outframe = ttk.LabelFrame(frame, text=_('Output')) # Section heading in settings
outframe.grid(padx=10, pady=10, sticky=tk.NSEW)
outframe.grid(padx=10, pady=5, sticky=tk.NSEW)
output = config.getint('output') or (config.OUT_EDDN | config.OUT_SHIP_EDS)
ttk.Label(outframe, text=_('Please choose what data to save')).grid(row=0, columnspan=2, padx=5, pady=3, sticky=tk.W)
self.out_eddn= tk.IntVar(value = (output & config.OUT_EDDN) and 1 or 0)
ttk.Checkbutton(outframe, text=_('Send station data to the Elite Dangerous Data Network'), variable=self.out_eddn, command=self.outvarchanged).grid(row=1, columnspan=2, padx=5, sticky=tk.W)
self.out_csv = tk.IntVar(value = (output & config.OUT_CSV ) and 1 or 0)
ttk.Checkbutton(outframe, text=_('Market data in CSV format file'), variable=self.out_csv, command=self.outvarchanged).grid(row=2, columnspan=2, padx=5, sticky=tk.W)
self.out_bpc = tk.IntVar(value = (output & config.OUT_BPC ) and 1 or 0)
ttk.Checkbutton(outframe, text=_("Market data in Slopey's BPC format file"), variable=self.out_bpc, command=self.outvarchanged).grid(row=3, columnspan=2, padx=5, sticky=tk.W)
self.out_td = tk.IntVar(value = (output & config.OUT_TD ) and 1 or 0)
ttk.Checkbutton(outframe, text=_('Market data in Trade Dangerous format file'), variable=self.out_td, command=self.outvarchanged).grid(row=4, columnspan=2, padx=5, sticky=tk.W)
self.out_ship_eds= tk.IntVar(value = (output & config.OUT_SHIP_EDS) and 1 or 0)
ttk.Checkbutton(outframe, text=_('Ship loadout in E:D Shipyard format file'), variable=self.out_ship_eds, command=self.outvarchanged).grid(row=5, columnspan=2, padx=5, pady=(5,0), sticky=tk.W)
self.out_ship_coriolis= tk.IntVar(value = (output & config.OUT_SHIP_CORIOLIS) and 1 or 0)
ttk.Checkbutton(outframe, text=_('Ship loadout in Coriolis format file'), variable=self.out_ship_coriolis, command=self.outvarchanged).grid(row=6, columnspan=2, padx=5, sticky=tk.W)
self.out_log_edsm = tk.IntVar(value = (output & config.OUT_LOG_EDSM ) and 1 or 0)
ttk.Checkbutton(outframe, text=_('Send flight log to Elite Dangerous Star Map'), variable=self.out_log_edsm, command=self.outvarchanged).grid(row=7, columnspan=2, padx=5, pady=(5,0), sticky=tk.W)
self.out_log_file = tk.IntVar(value = (output & config.OUT_LOG_FILE ) and 1 or 0)
ttk.Checkbutton(outframe, text=_('Flight log in CSV format file'), variable=self.out_log_file, command=self.outvarchanged).grid(row=8, columnspan=2, padx=5, sticky=tk.W)
ttk.Label(outframe, text=_('Please choose what data to save')).grid(row=0, padx=5, pady=3, sticky=tk.W)
self.out_eddn= tk.IntVar(value = (output & config.OUT_EDDN) and 1)
ttk.Checkbutton(outframe, text=_('Send station data to the Elite Dangerous Data Network'), variable=self.out_eddn, command=self.outvarchanged).grid(row=1, padx=5, sticky=tk.W)
self.out_csv = tk.IntVar(value = (output & config.OUT_CSV ) and 1)
ttk.Checkbutton(outframe, text=_('Market data in CSV format file'), variable=self.out_csv, command=self.outvarchanged).grid(row=2, padx=5, sticky=tk.W)
self.out_bpc = tk.IntVar(value = (output & config.OUT_BPC ) and 1)
ttk.Checkbutton(outframe, text=_("Market data in Slopey's BPC format file"), variable=self.out_bpc, command=self.outvarchanged).grid(row=3, padx=5, sticky=tk.W)
self.out_td = tk.IntVar(value = (output & config.OUT_TD ) and 1)
ttk.Checkbutton(outframe, text=_('Market data in Trade Dangerous format file'), variable=self.out_td, command=self.outvarchanged).grid(row=4, padx=5, sticky=tk.W)
self.out_ship_eds= tk.IntVar(value = (output & config.OUT_SHIP_EDS) and 1)
ttk.Checkbutton(outframe, text=_('Ship loadout in E:D Shipyard format file'), variable=self.out_ship_eds, command=self.outvarchanged).grid(row=5, padx=5, pady=(5,0), sticky=tk.W)
self.out_ship_coriolis= tk.IntVar(value = (output & config.OUT_SHIP_CORIOLIS) and 1)
ttk.Checkbutton(outframe, text=_('Ship loadout in Coriolis format file'), variable=self.out_ship_coriolis, command=self.outvarchanged).grid(row=6, padx=5, sticky=tk.W)
self.out_log_edsm = tk.IntVar(value = (output & config.OUT_LOG_EDSM) and 1)
ttk.Checkbutton(outframe, text=_('Send flight log to Elite Dangerous Star Map'), variable=self.out_log_edsm, command=self.outvarchanged).grid(row=7, padx=5, pady=(5,0), sticky=tk.W)
self.out_log_file = tk.IntVar(value = (output & config.OUT_LOG_FILE) and 1)
ttk.Checkbutton(outframe, text=_('Flight log in CSV format file'), variable=self.out_log_file, command=self.outvarchanged).grid(row=8, padx=5, sticky=tk.W)
self.out_log_auto = tk.IntVar(value = monitor.logdir and (output & config.OUT_LOG_AUTO) and 1 or 0)
if monitor.logdir:
self.out_log_auto_button = ttk.Checkbutton(outframe, text=_('Automatically make a log entry on entering a system'), variable=self.out_log_auto, command=self.outvarchanged) # Output setting
self.out_log_auto_button.grid(row=9, padx=5, sticky=tk.W)
self.out_log_auto_text = ttk.Label(outframe)
self.dir_label = ttk.Label(frame, text=_('File location'), foreground=style.lookup('TLabelframe.Label', 'foreground')) # Section heading in settings
dirframe = ttk.LabelFrame(frame, labelwidget = self.dir_label)
dirframe.grid(padx=10, pady=10, sticky=tk.NSEW)
dirframe.grid(padx=10, pady=5, sticky=tk.NSEW)
dirframe.columnconfigure(0, weight=1)
self.outdir = ttk.Entry(dirframe, takefocus=False)
@ -128,7 +134,7 @@ class PreferencesDialog(tk.Toplevel):
self.edsm_label = HyperlinkLabel(frame, text=_('Elite Dangerous Star Map credentials'), disabledforeground=style.lookup('TLabelframe.Label', 'foreground'), url='http://www.edsm.net/settings/api', underline=True) # Section heading in settings
edsmframe = ttk.LabelFrame(frame, labelwidget = self.edsm_label)
edsmframe.grid(padx=10, pady=10, sticky=tk.NSEW)
edsmframe.grid(padx=10, pady=5, sticky=tk.NSEW)
edsmframe.columnconfigure(1, weight=1)
ttk.Label(edsmframe, text=_('Cmdr name')).grid(row=0, sticky=tk.W) # EDSM & privacy setting
@ -151,7 +157,7 @@ class PreferencesDialog(tk.Toplevel):
self.hotkey_play = tk.IntVar(value = not config.getint('hotkey_mute'))
hotkeyframe = ttk.LabelFrame(frame, text=platform == 'darwin' and _('Keyboard shortcut') or # Section heading in settings on OSX
_('Hotkey')) # Section heading in settings on Windows
hotkeyframe.grid(padx=10, pady=10, sticky=tk.NSEW)
hotkeyframe.grid(padx=10, pady=5, sticky=tk.NSEW)
hotkeyframe.columnconfigure(1, weight=1)
if platform == 'darwin' and not was_accessible_at_launch:
if AXIsProcessTrusted():
@ -171,10 +177,10 @@ class PreferencesDialog(tk.Toplevel):
self.hotkey_play_btn.grid(row=2, columnspan=2, padx=5, sticky=tk.W)
privacyframe = ttk.LabelFrame(frame, text=_('Privacy')) # Section heading in settings
privacyframe.grid(padx=10, pady=10, sticky=tk.NSEW)
privacyframe.grid(padx=10, pady=5, sticky=tk.NSEW)
self.out_anon= tk.IntVar(value = config.getint('anonymous') and 1)
ttk.Label(privacyframe, text=_('How do you want to be identified in the saved data')).grid(row=0, columnspan=2, padx=5, sticky=tk.W)
ttk.Label(privacyframe, text=_('How do you want to be identified in the saved data')).grid(row=0, padx=5, sticky=tk.W)
ttk.Radiobutton(privacyframe, text=_('Cmdr name'), variable=self.out_anon, value=0).grid(padx=5, sticky=tk.W) # Privacy setting
ttk.Radiobutton(privacyframe, text=_('Pseudo-anonymized ID'), variable=self.out_anon, value=1).grid(padx=5, sticky=tk.W) # Privacy setting
@ -182,17 +188,20 @@ class PreferencesDialog(tk.Toplevel):
self.protocol("WM_DELETE_WINDOW", self.apply) # close button applies changes
else:
buttonframe = ttk.Frame(frame)
buttonframe.grid(padx=10, pady=10, sticky=tk.NSEW)
buttonframe.grid(padx=10, pady=5, sticky=tk.NSEW)
buttonframe.columnconfigure(0, weight=1)
ttk.Label(buttonframe).grid(row=0, column=0) # spacer
ttk.Button(buttonframe, text=_('OK'), command=self.apply).grid(row=0, column=1, sticky=tk.E)
button = ttk.Button(buttonframe, text=_('OK'), command=self.apply)
button.grid(row=0, column=1, sticky=tk.E)
button.bind("<Return>", lambda event:self.apply())
self.protocol("WM_DELETE_WINDOW", self._destroy)
# Selectively disable buttons depending on output settings
self.outvarchanged()
# disable hotkey for the duration
# disable hotkey and log monitoring for the duration
hotkeymgr.unregister()
monitor.stop()
# wait for window to appear on screen before calling grab_set
self.wait_visibility()
@ -205,6 +214,20 @@ class PreferencesDialog(tk.Toplevel):
self.outbutton['state'] = local and tk.NORMAL or tk.DISABLED
self.outdir['state'] = local and 'readonly' or tk.DISABLED
if monitor.logdir:
log = self.out_log_edsm.get() or self.out_log_file.get()
self.out_log_auto_button['state'] = log and tk.NORMAL or tk.DISABLED
self.out_log_auto_text['text'] = ''
if log and self.out_log_auto.get():
if not monitor.enable_logging():
self.out_log_auto_text['text'] = "Can't enable automatic logging!" # Shouldn't happen - don't translate
self.out_log_auto_text.grid(row=10, padx=(25,5), sticky=tk.EW)
elif monitor.restart_required():
self.out_log_auto_text['text'] = _('Re-start Elite: Dangerous for automatic logging') # Output settings prompt
self.out_log_auto_text.grid(row=10, padx=(25,5), sticky=tk.EW)
edsm = self.out_log_edsm.get()
self.edsm_label['state'] = edsm and tk.NORMAL or tk.DISABLED
self.edsm_cmdr['state'] = edsm and tk.NORMAL or tk.DISABLED
@ -290,7 +313,7 @@ class PreferencesDialog(tk.Toplevel):
config.set('username', self.username.get().strip())
config.set('password', self.password.get().strip())
config.set('output', (self.out_eddn.get() and config.OUT_EDDN or 0) + (self.out_bpc.get() and config.OUT_BPC or 0) + (self.out_td.get() and config.OUT_TD or 0) + (self.out_csv.get() and config.OUT_CSV or 0) + (self.out_ship_eds.get() and config.OUT_SHIP_EDS or 0) + (self.out_log_file.get() and config.OUT_LOG_FILE or 0) + (self.out_ship_coriolis.get() and config.OUT_SHIP_CORIOLIS or 0) + (self.out_log_edsm.get() and config.OUT_LOG_EDSM or 0))
config.set('output', (self.out_eddn.get() and config.OUT_EDDN) + (self.out_bpc.get() and config.OUT_BPC) + (self.out_td.get() and config.OUT_TD) + (self.out_csv.get() and config.OUT_CSV) + (self.out_ship_eds.get() and config.OUT_SHIP_EDS) + (self.out_log_file.get() and config.OUT_LOG_FILE) + (self.out_ship_coriolis.get() and config.OUT_SHIP_CORIOLIS) + (self.out_log_edsm.get() and config.OUT_LOG_EDSM) + (self.out_log_auto.get() and config.OUT_LOG_AUTO))
config.set('outdir', expanduser(self.outdir.get()))
config.set('edsm_cmdrname', self.edsm_cmdr.get().strip())
@ -309,8 +332,11 @@ class PreferencesDialog(tk.Toplevel):
self.callback()
def _destroy(self):
# Re-enable hotkey monitoring before exit
# Re-enable hotkey and log monitoring before exit
hotkeymgr.register(self.parent, config.getint('hotkey_code'), config.getint('hotkey_mods'))
if (config.getint('output') & config.OUT_LOG_AUTO) and (config.getint('output') & (config.OUT_LOG_AUTO|config.OUT_LOG_EDSM)):
monitor.enable_logging()
monitor.start()
self.destroy()
if platform == 'darwin':
@ -371,6 +397,7 @@ class AuthenticationDialog(tk.Toplevel):
self.code.focus_set()
ttk.Label(frame).grid(row=1, column=2) # spacer
self.button = ttk.Button(frame, text=_('OK'), command=self.apply, state=tk.DISABLED)
self.button.bind("<Return>", lambda event:self.apply())
self.button.grid(row=1, column=3, sticky=tk.E)
for child in frame.winfo_children():