diff --git a/EDMarketConnector.py b/EDMarketConnector.py index 17a42387..6588ef5e 100755 --- a/EDMarketConnector.py +++ b/EDMarketConnector.py @@ -155,12 +155,6 @@ class AppWindow: if platform != 'linux2': # update_idletasks() doesn't allow for the menubar on Linux self.w.maxsize(-1, h) # Maximum height = initial height - # First run - if not config.get('username') or not config.get('password'): - prefs.PreferencesDialog(self.w, self.login) - else: - self.login() - # Load updater after UI creation (for WinSparkle) import update self.updater = update.Updater(self.w) @@ -176,6 +170,12 @@ class AppWindow: monitor.enable_logging() monitor.start(self.w) + # First run + if not config.get('username') or not config.get('password'): + prefs.PreferencesDialog(self.w, self.login) + else: + self.login() + # call after credentials have changed def login(self): self.status['text'] = _('Logging in...') @@ -201,6 +201,9 @@ class AppWindow: except Exception as e: if __debug__: print_exc() self.status['text'] = unicode(e) + + if not self.status['text'] and monitor.restart_required(): + self.status['text'] = _('Re-start Elite: Dangerous for automatic log entries') # Status bar message on launch self.cooldown() # callback after verification code diff --git a/L10n/en.template b/L10n/en.template index 0118283d..cf9d23ab 100644 --- a/L10n/en.template +++ b/L10n/en.template @@ -139,6 +139,9 @@ /* Privacy setting. [prefs.py] */ "Pseudo-anonymized ID" = "Pseudo-anonymized ID"; +/* Status bar message on launch. [EDMarketConnector.py] */ +"Re-start Elite: Dangerous for automatic log entries" = "Re-start Elite: Dangerous for automatic log entries"; + /* Output settings prompt. [prefs.py] */ "Re-start Elite: Dangerous to use this feature" = "Re-start Elite: Dangerous to use this feature"; diff --git a/L10n/fr.strings b/L10n/fr.strings index 7dbea20b..a6672b77 100644 --- a/L10n/fr.strings +++ b/L10n/fr.strings @@ -201,3 +201,6 @@ /* [EDMarketConnector.py] */ "Error: Can't get market data!" = "Erreur: Impossible d'obtenir les données du marché!"; + +/* Status bar message on launch. [EDMarketConnector.py] */ +"Re-start Elite: Dangerous for automatic log entries" = "Re-démarrer Elite: Dangereux pour les entrées de journal automatique"; diff --git a/L10n/it.strings b/L10n/it.strings index 1d2739d7..a84a9bf9 100644 --- a/L10n/it.strings +++ b/L10n/it.strings @@ -197,7 +197,10 @@ "Automatically make a log entry on entering a system" = "Inserire automaticamente una log entry entrando in un sistema"; /* Output settings prompt. [prefs.py] */ -"Re-start Elite: Dangerous to use this feature" = "Riavviare Elite:Dangerous per usare questa funzione"; +"Re-start Elite: Dangerous to use this feature" = "Riavviare Elite: Dangerous per usare questa funzione"; /* [EDMarketConnector.py] */ "Error: Can't get market data!" = "Errore: Non riesco a ottenere il market data!"; + +/* Status bar message on launch. [EDMarketConnector.py] */ +"Re-start Elite: Dangerous for automatic log entries" = "Riavviare Elite: Dangerous per una log entry automatica"; diff --git a/L10n/pl.strings b/L10n/pl.strings index 1614391a..40143da9 100644 --- a/L10n/pl.strings +++ b/L10n/pl.strings @@ -192,3 +192,6 @@ /* [EDMarketConnector.py] */ "Sending data to EDSM..." = "Wysłanie danych do EDSM..."; + +/* Output settings prompt. [prefs.py] */ +"Re-start Elite: Dangerous to use this feature" = ""; diff --git a/monitor.py b/monitor.py index 0ec89ba3..57622215 100644 --- a/monitor.py +++ b/monitor.py @@ -1,12 +1,16 @@ +import atexit import re import threading from os import listdir, pardir, rename, unlink -from os.path import exists, isdir, isfile, join +from os.path import basename, exists, isdir, isfile, join from platform import machine from sys import platform from time import strptime, localtime, mktime, sleep, time from datetime import datetime +from watchdog.observers import Observer +from watchdog.events import FileSystemEventHandler + if __debug__: from traceback import print_exc @@ -60,15 +64,29 @@ elif platform=='win32': return True -class EDLogs: +class EDLogs(FileSystemEventHandler): def __init__(self): + FileSystemEventHandler.__init__(self) # futureproofing - not need for current version of watchdog self.root = None self.logdir = self._logdir() + self.logfile = None self.logging_enabled = self._logging_enabled self._restart_required = False - self.observer = None - self.last_event = None + self.thread = None + self.last_event = None # for communicating the Jump event + + if self.logdir: + # Set up a watchog observer. This is low overhead so is left running irrespective of whether monitoring is desired. + observer = Observer() + observer.daemon = True + observer.schedule(self, self.logdir) + observer.start() + atexit.register(observer.stop) + + # Latest pre-existing logfile - e.g. if E:D is already running. Assumes logs sort alphabetically. + logfiles = sorted([x for x in listdir(self.logdir) if x.startswith('netLog.')]) + self.logfile = logfiles and join(self.logdir, logfiles[-1]) or None def enable_logging(self): if self.logging_enabled(): @@ -137,17 +155,22 @@ class EDLogs: return False if self.running(): return True - self.observer = threading.Thread(target = self.worker, name = 'netLog worker') - self.observer.daemon = True - self.observer.start() + self.thread = threading.Thread(target = self.worker, name = 'netLog worker') + self.thread.daemon = True + self.thread.start() return True def stop(self): - self.observer = None # Orphan the worker thread + self.thread = None # Orphan the worker thread self.last_event = None def running(self): - return self.observer and self.observer.is_alive() + return self.thread and self.thread.is_alive() + + def on_created(self, event): + # watchdog callback, e.g. client (re)started. + if not event.is_directory and basename(event.src_path).startswith('netLog.'): + self.logfile = event.src_path def worker(self): # e.g. "{18:11:44} System:22(Gamma Doradus) Body:3 Pos:(3.69928e+07,1.13173e+09,-1.75892e+08) \r\n". @@ -155,27 +178,21 @@ class EDLogs: regexp = re.compile(r'\{(.+)\} System:\d+\((.+)\) Body:') # 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 + logfile = self.logfile if logfile: - loghandle = open(join(self.logdir, logfile), 'rt') + loghandle = open(logfile, 'rt') loghandle.seek(0, 2) # seek to EOF else: loghandle = None while True: - # Check whether we're still supposed to be running - if threading.current_thread() != self.observer: - return # Terminate - - # 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 + # Check whether new log file started, e.g. client (re)started. + newlogfile = self.logfile if logfile != newlogfile: logfile = newlogfile if loghandle: loghandle.close() - loghandle = open(join(self.logdir, logfile), 'rt') + loghandle = open(logfile, 'rt') if logfile: system = visited = None @@ -201,6 +218,10 @@ class EDLogs: sleep(10) # New system gets posted to log file before hyperspace ends, so don't need to poll too often + # Check whether we're still supposed to be running + if threading.current_thread() != self.thread: + return # Terminate + if platform=='darwin':