mirror of
https://github.com/EDCD/EDMarketConnector.git
synced 2025-04-14 08:17:13 +03:00
Add support for sending flight log to EDSM. Export existing flight log to EDSM the first time this is enabled.
This commit is contained in:
parent
a74a928764
commit
60caf24c8d
@ -179,7 +179,7 @@ class AppWindow:
|
||||
self.status['text'] = ''
|
||||
|
||||
# Try to obtain exclusive lock on flight log ASAP
|
||||
if config.getint('output') & config.OUT_LOG:
|
||||
if config.getint('output') & config.OUT_LOG_FILE:
|
||||
try:
|
||||
flightlog.openlog()
|
||||
except Exception as e:
|
||||
@ -251,25 +251,29 @@ class AppWindow:
|
||||
self.system['text'] = data.get('lastSystem') and data.get('lastSystem').get('name') or ''
|
||||
self.station['text'] = data.get('commander') and data.get('commander').get('docked') and data.get('lastStarport') and data.get('lastStarport').get('name') or (EDDB.system(self.system['text']) and self.STATION_UNDOCKED or '')
|
||||
self.edit_menu.entryconfigure(_('Copy'), state=tk.NORMAL)
|
||||
self.edsm.start_lookup(self.system['text'], EDDB.system(self.system['text']))
|
||||
self.system['image'] = self.edsm.result['img']
|
||||
self.w.after(int(EDSM_POLL * 1000), self.edsmpoll)
|
||||
|
||||
# stuff we can do when not docked
|
||||
if config.getint('output') & config.OUT_LOG:
|
||||
flightlog.export(data)
|
||||
if config.getint('output') & config.OUT_SHIP_EDS:
|
||||
loadout.export(data)
|
||||
if config.getint('output') & config.OUT_SHIP_CORIOLIS:
|
||||
coriolis.export(data)
|
||||
if config.getint('output') & config.OUT_LOG_FILE:
|
||||
flightlog.export(data)
|
||||
if config.getint('output') & config.OUT_LOG_EDSM:
|
||||
self.status['text'] = _('Sending data to EDSM...')
|
||||
self.w.update_idletasks()
|
||||
edsm.export(data, lambda:self.edsm.lookup(self.system['text'], EDDB.system(self.system['text']))) # Do EDSM lookup during EDSM export
|
||||
else:
|
||||
self.edsm.start_lookup(self.system['text'], EDDB.system(self.system['text']))
|
||||
self.edsmpoll()
|
||||
|
||||
if not (config.getint('output') & (config.OUT_CSV|config.OUT_TD|config.OUT_BPC|config.OUT_EDDN)):
|
||||
# no further output requested
|
||||
# no station data requested - we're done
|
||||
self.status['text'] = strftime(_('Last updated at {HH}:{MM}:{SS}').format(HH='%H', MM='%M', SS='%S').encode('utf-8'), localtime(querytime)).decode('utf-8')
|
||||
|
||||
elif not data['commander'].get('docked'):
|
||||
self.status['text'] = _("You're not docked at a station!")
|
||||
# signal as error becuase sometimes the server hosting the Companion API hasn't caught up
|
||||
# signal as error because the user might actually be docked but the server hosting the Companion API hasn't caught up
|
||||
if play_sound: hotkeymgr.play_bad()
|
||||
|
||||
else:
|
||||
|
11
README.md
11
README.md
@ -43,7 +43,7 @@ combination that you use to log into the Elite: Dangerous launcher, and is requi
|
||||
|
||||
You can also choose here what data to save (refer to the next section for details), whether to set up a hotkey so you don't have to switch to the app in order to “Update”, and whether to attach your Cmdr name or a [pseudo-anonymized](http://en.wikipedia.org/wiki/Pseudonymity) ID to the data.
|
||||
|
||||
You are next prompted to authenticate with a “verification code”, which you will shortly receive by email from Frontier.
|
||||
The first time that you hit “Update” you will be prompted to authenticate with a “verification code”, which you will shortly receive by email from Frontier.
|
||||
Note that each “verification code” is one-time only - if you enter the code incorrectly or quit the app before
|
||||
authenticating you will need to wait for Frontier to send you a new code.
|
||||
|
||||
@ -56,15 +56,16 @@ This app can save a variety of data in a variety of formats:
|
||||
|
||||
* Market data
|
||||
* Elite Dangerous Data Network - sends commodity market, outfitting and shipyard data to “[EDDN](http://eddn-gateway.elite-markets.net/)” from where you and others can use it via online trading tools such as [eddb](http://eddb.io/), [Elite Trade Net](http://etn.io/), [Inara](http://inara.cz), [ED-TD](http://ed-td.space/), [Roguey's](http://roguey.co.uk/elite-dangerous/), etc.
|
||||
* Slopey's BPC format - saves commodity market data as files that you can load into [Slopey's BPC Market Tool](https://forums.frontier.co.uk/showthread.php?t=76081).
|
||||
* Trade Dangerous format - saves commodity market data as files that you can load into [Trade Dangerous](https://bitbucket.org/kfsone/tradedangerous/wiki/Home).
|
||||
* CSV format - saves commodity market data as files that you can upload to [Thrudd's Trading Tools](http://www.elitetradingtool.co.uk/), [Inara](http://inara.cz) or [mEDI's Elite Tools](https://github.com/mEDI-S/mEDI_s-Elite-Tools).
|
||||
* Slopey's BPC format file - saves commodity market data as files that you can load into [Slopey's BPC Market Tool](https://forums.frontier.co.uk/showthread.php?t=76081).
|
||||
* Trade Dangerous format file - saves commodity market data as files that you can load into [Trade Dangerous](https://bitbucket.org/kfsone/tradedangerous/wiki/Home).
|
||||
* CSV format file - saves commodity market data as files that you can upload to [Thrudd's Trading Tools](http://www.elitetradingtool.co.uk/), [Inara](http://inara.cz) or [mEDI's Elite Tools](https://github.com/mEDI-S/mEDI_s-Elite-Tools).
|
||||
|
||||
* Ship loadout
|
||||
* After every outfitting change saves a record of your ship loadout as a file that you can open in a text editor and that you can import into [E:D Shipyard](http://www.edshipyard.com) or [Coriolis](http://coriolis.io).
|
||||
|
||||
* Flight log
|
||||
* Adds a record of your location, ship and cargo to a file that you can open in a text editor or a spreadsheet program such as Excel. Note: Don't edit, rename or move this file - take a copy if you wish to change it.
|
||||
* Elite Dangerous Star Map - sends a record of your location to “[EDSM](http://www.edsm.net/)” where you can view your logs under My account → Exploration Logs, and optionally add private comments about a system.
|
||||
* CSV format file - adds a record of your location, ship and cargo to a file that you can open in a text editor or a spreadsheet program such as Excel. Note: Don't edit, rename or move this file - take a copy if you wish to change it.
|
||||
|
||||
By default these files will be placed in your Documents folder. Since this app will create a lot of files if you use it for a while you may wish to create a separate folder for the files and tell the app to place them there.
|
||||
|
||||
|
@ -70,9 +70,10 @@ class Config:
|
||||
OUT_TD = 4
|
||||
OUT_CSV = 8
|
||||
OUT_SHIP_EDS = 16
|
||||
OUT_LOG = 32
|
||||
OUT_LOG_FILE = 32
|
||||
#OUT_STAT = 64 # No longer available
|
||||
OUT_SHIP_CORIOLIS = 128
|
||||
OUT_LOG_EDSM = 256
|
||||
|
||||
if platform=='darwin':
|
||||
|
||||
|
89
edsm.py
89
edsm.py
@ -1,10 +1,14 @@
|
||||
import requests
|
||||
import threading
|
||||
from sys import platform
|
||||
import time
|
||||
import urllib
|
||||
|
||||
import Tkinter as tk
|
||||
|
||||
from config import config
|
||||
import flightlog
|
||||
|
||||
if __debug__:
|
||||
from traceback import print_exc
|
||||
|
||||
@ -24,18 +28,43 @@ class EDSM:
|
||||
EDSM._IMG_NEW = tk.PhotoImage(data = 'R0lGODlhEAAQAMZwANKVHtWcIteiHuiqLPCuHOS1MN22ZeW7ROG6Zuu9MOy+K/i8Kf/DAuvCVf/FAP3BNf/JCf/KAPHHSv7ESObHdv/MBv/GRv/LGP/QBPXOPvjPQfjQSvbRSP/UGPLSae7Sfv/YNvLXgPbZhP7dU//iI//mAP/jH//kFv7fU//fV//ebv/iTf/iUv/kTf/iZ/vgiP/hc/vgjv/jbfriiPriiv7ka//if//jd//sJP/oT//tHv/mZv/sLf/rRP/oYv/rUv/paP/mhv/sS//oc//lkf/mif/sUf/uPv/qcv/uTv/uUv/vUP/qhP/xP//pm//ua//sf//ubf/wXv/thv/tif/slv/tjf/smf/yYP/ulf/2R//2Sv/xkP/2av/0gP/ylf/2df/0i//0j//0lP/5cP/7a//1p//5gf/7ev/3o//2sf/5mP/6kv/2vP/3y//+jP///////////////////////////////////////////////////////////////yH5BAEKAH8ALAAAAAAQABAAAAePgH+Cg4SFhoJKPIeHYT+LhVppUTiPg2hrUkKPXWdlb2xHJk9jXoNJQDk9TVtkYCUkOy4wNjdGfy1UXGJYOksnPiwgFwwYg0NubWpmX1ArHREOFYUyWVNIVkxXQSoQhyMoNVUpRU5EixkcMzQaGy8xhwsKHiEfBQkSIg+GBAcUCIIBBDSYYGiAAUMALFR6FAgAOw==')
|
||||
EDSM._IMG_ERROR = tk.PhotoImage(data = 'R0lGODlhDgAOAIABAAAAAP///yH5BAEKAAEALAAAAAAOAA4AAAIcjIGJxqHaIJPypBYvzms77X1dWHlliKYmuI5GAQA7') # BBC Mode 5 '?'
|
||||
|
||||
def lookup(self, system_name, known=0):
|
||||
self.cancel_lookup()
|
||||
|
||||
if system_name in self.syscache: # Cache URLs of systems with known coordinates
|
||||
self.result = { 'img': EDSM._IMG_KNOWN, 'url': self.syscache[system_name], 'done': True }
|
||||
elif known:
|
||||
self.result = { 'img': EDSM._IMG_KNOWN, 'url': 'http://www.edsm.net/needed-distances?systemName=%s' % urllib.quote(system_name), 'done': True } # default URL
|
||||
self.thread = threading.Thread(target = self.known, name = 'EDSM worker', args = (system_name, self.result))
|
||||
else:
|
||||
self.result = { 'img': '', 'url': 'http://www.edsm.net/needed-distances?systemName=%s' % urllib.quote(system_name), 'done': True } # default URL
|
||||
r = requests.get('http://www.edsm.net/api-v1/system?sysname=%s&coords=1' % urllib.quote(system_name), timeout=EDSM._TIMEOUT)
|
||||
r.raise_for_status()
|
||||
data = r.json()
|
||||
|
||||
if data == -1:
|
||||
# System not present - but don't create it on the assumption that the caller will
|
||||
result['img'] = EDSM._IMG_NEW
|
||||
elif data.get('coords'):
|
||||
result['img'] = EDSM._IMG_KNOWN
|
||||
self.thread = threading.Thread(target = self.known, name = 'EDSM worker', args = (system_name, self.result))
|
||||
else:
|
||||
result['img'] = EDSM._IMG_UNKNOWN
|
||||
|
||||
# Asynchronous version of the above
|
||||
def start_lookup(self, system_name, known=0):
|
||||
self.cancel_lookup()
|
||||
|
||||
# Cache URLs of systems with known coordinates
|
||||
if system_name in self.syscache:
|
||||
if system_name in self.syscache: # Cache URLs of systems with known coordinates
|
||||
self.result = { 'img': EDSM._IMG_KNOWN, 'url': self.syscache[system_name], 'done': True }
|
||||
return
|
||||
|
||||
self.result = { 'img': '', 'url': 'http://www.edsm.net/needed-distances?systemName=%s' % urllib.quote(system_name), 'done': False } # default URL
|
||||
self.thread = threading.Thread(target = known and self.known or self.worker, name = 'EDSM worker', args = (system_name, self.result))
|
||||
self.thread.daemon = True
|
||||
self.thread.start()
|
||||
elif known:
|
||||
self.result = { 'img': EDSM._IMG_KNOWN, 'url': 'http://www.edsm.net/needed-distances?systemName=%s' % urllib.quote(system_name), 'done': True } # default URL
|
||||
self.thread = threading.Thread(target = self.known, name = 'EDSM worker', args = (system_name, self.result))
|
||||
else:
|
||||
self.result = { 'img': '', 'url': 'http://www.edsm.net/needed-distances?systemName=%s' % urllib.quote(system_name), 'done': False } # default URL
|
||||
self.thread = threading.Thread(target = self.worker, name = 'EDSM worker', args = (system_name, self.result))
|
||||
self.thread.daemon = True
|
||||
self.thread.start()
|
||||
|
||||
def cancel_lookup(self):
|
||||
self.thread = None # orphan any existing thread
|
||||
@ -53,6 +82,8 @@ class EDSM:
|
||||
result['done'] = True # give feedback immediately
|
||||
requests.get('http://www.edsm.net/api-v1/url?sysname=%s' % urllib.quote(system_name), timeout=EDSM._TIMEOUT) # creates system
|
||||
elif data.get('coords'):
|
||||
result['img'] = EDSM._IMG_KNOWN
|
||||
result['done'] = True # give feedback immediately
|
||||
self.known(system_name, result)
|
||||
else:
|
||||
result['img'] = EDSM._IMG_UNKNOWN
|
||||
@ -64,8 +95,6 @@ class EDSM:
|
||||
# Worker for known known systems - saves initial EDSM API call
|
||||
def known(self, system_name, result):
|
||||
# Prefer to send user to "Show distances" page for systems with known coordinates
|
||||
result['img'] = EDSM._IMG_KNOWN
|
||||
result['done'] = True # give feedback immediately
|
||||
try:
|
||||
r = requests.get('http://www.edsm.net/api-v1/url?sysname=%s' % urllib.quote(system_name), timeout=EDSM._TIMEOUT)
|
||||
r.raise_for_status()
|
||||
@ -73,3 +102,43 @@ class EDSM:
|
||||
result['url'] = self.syscache[system_name] = data['url']['show-system']
|
||||
except:
|
||||
if __debug__: print_exc()
|
||||
|
||||
|
||||
# Flight log - http://www.edsm.net/api-logs
|
||||
def export(data, edsmlookupfn):
|
||||
|
||||
querytime = config.getint('querytime') or int(time.time())
|
||||
|
||||
try:
|
||||
# Look up the system before adding it to the log, since adding it to the log has the side-effect of creating it
|
||||
edsmlookupfn()
|
||||
|
||||
r = requests.get('http://www.edsm.net/api-logs-v1/set-log?commanderName=%s&apiKey=%s&systemName=%s&dateVisited=%s' % (urllib.quote(config.get('edsm_cmdrname')), urllib.quote(config.get('edsm_apikey')), urllib.quote(data['lastSystem']['name']), urllib.quote(time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(querytime)))), timeout=EDSM._TIMEOUT)
|
||||
r.raise_for_status()
|
||||
reply = r.json()
|
||||
(msgnum, msg) = reply['msgnum'], reply['msg']
|
||||
except:
|
||||
if __debug__: print_exc()
|
||||
raise Exception(_("Error: Can't connect to EDSM"))
|
||||
|
||||
# Message numbers: 1xx = OK, 2xx = fatal error, 3xx = error (but not generated in practice), 4xx = ignorable errors
|
||||
if msgnum // 100 not in (1,4):
|
||||
raise Exception(_('Error: EDSM {MSG}').format(MSG=msg))
|
||||
|
||||
if not config.getint('edsm_historical'):
|
||||
config.set('edsm_historical', 1)
|
||||
thread = threading.Thread(target = export_historical, name = 'EDSM export')
|
||||
thread.daemon = True
|
||||
thread.start()
|
||||
|
||||
# Make best effort to export existing flight log file. Be silent on error.
|
||||
def export_historical():
|
||||
try:
|
||||
for (timestamp, system_name) in flightlog.logs():
|
||||
r = requests.get('http://www.edsm.net/api-logs-v1/set-log?commanderName=%s&apiKey=%s&systemName=%s&dateVisited=%s' % (urllib.quote(config.get('edsm_cmdrname')), urllib.quote(config.get('edsm_apikey')), urllib.quote(system_name), urllib.quote(time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(timestamp)))), timeout=EDSM._TIMEOUT)
|
||||
r.raise_for_status()
|
||||
|
||||
if r.json()['msgnum'] // 100 == 2:
|
||||
raise Exception()
|
||||
except:
|
||||
if __debug__: print_exc()
|
||||
|
16
flightlog.py
16
flightlog.py
@ -39,9 +39,6 @@ def openlog():
|
||||
|
||||
def export(data):
|
||||
|
||||
def elapsed(game_time):
|
||||
return '%3d:%02d:%02d' % ((game_time // 3600) % 3600, (game_time // 60) % 60, game_time % 60)
|
||||
|
||||
querytime = config.getint('querytime') or int(time.time())
|
||||
|
||||
openlog()
|
||||
@ -60,3 +57,16 @@ def export(data):
|
||||
','.join([('%d %s' % (commodities[k], k)) for k in sorted(commodities)])))
|
||||
|
||||
logfile.flush()
|
||||
|
||||
|
||||
# return log as list of (timestamp, system_name)
|
||||
def logs():
|
||||
entries = []
|
||||
with open(join(config.get('outdir'), 'Flight Log.csv'), 'rU') as f:
|
||||
f.readline() # Assume header
|
||||
for line in f:
|
||||
if not line.strip(): continue
|
||||
cols = line.split(',')
|
||||
assert len(cols) >= 3, cols
|
||||
entries.append((time.mktime(time.strptime('%sT%s' % (cols[0], cols[1]), '%Y-%m-%dT%H:%M:%S')), cols[2])) # Convert from local time to UTC
|
||||
return entries
|
||||
|
103
prefs.py
103
prefs.py
@ -1,12 +1,13 @@
|
||||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from os.path import dirname, isdir, sep
|
||||
from os.path import dirname, expanduser, isdir, sep
|
||||
from sys import platform
|
||||
|
||||
import Tkinter as tk
|
||||
import ttk
|
||||
import tkFileDialog
|
||||
from ttkHyperlinkLabel import HyperlinkLabel
|
||||
|
||||
from config import applongname, config
|
||||
from hotkey import hotkeymgr
|
||||
@ -64,6 +65,8 @@ class PreferencesDialog(tk.Toplevel):
|
||||
# http://wiki.tcl.tk/13428
|
||||
parent.call('tk::unsupported::MacWindowStyle', 'style', self, 'utility')
|
||||
|
||||
style = ttk.Style()
|
||||
|
||||
frame = ttk.Frame(self)
|
||||
frame.grid(sticky=tk.NSEW)
|
||||
|
||||
@ -88,34 +91,58 @@ class PreferencesDialog(tk.Toplevel):
|
||||
|
||||
outframe = ttk.LabelFrame(frame, text=_('Output')) # Section heading in settings
|
||||
outframe.grid(padx=10, pady=10, sticky=tk.NSEW)
|
||||
outframe.columnconfigure(0, weight=1)
|
||||
|
||||
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).grid(row=1, 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"), variable=self.out_bpc, command=self.outvarchanged).grid(row=2, 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'), variable=self.out_td, command=self.outvarchanged).grid(row=3, columnspan=2, padx=5, sticky=tk.W)
|
||||
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'), variable=self.out_csv, command=self.outvarchanged).grid(row=4, columnspan=2, padx=5, sticky=tk.W)
|
||||
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'), variable=self.out_ship_eds, command=self.outvarchanged).grid(row=5, columnspan=2, padx=5, sticky=tk.W)
|
||||
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'), variable=self.out_ship_coriolis, command=self.outvarchanged).grid(row=6, columnspan=2, padx=5, sticky=tk.W)
|
||||
self.out_log = tk.IntVar(value = (output & config.OUT_LOG ) and 1 or 0)
|
||||
ttk.Checkbutton(outframe, text=_('Flight log'), variable=self.out_log, command=self.outvarchanged).grid(row=7, columnspan=2, padx=5, sticky=tk.W)
|
||||
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=(platform=='darwin' and _('Where:') or # Output folder prompt on OSX
|
||||
_('File location:'))).grid(row=8, padx=5, pady=(5,0), sticky=tk.NSEW) # Output folder prompt on Windows
|
||||
self.outbutton = ttk.Button(outframe, text=(platform=='darwin' and _('Change...') or # Folder selection button on OSX
|
||||
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.columnconfigure(0, weight=1)
|
||||
|
||||
self.outdir = ttk.Entry(dirframe, takefocus=False)
|
||||
if config.get('outdir').startswith(expanduser('~')):
|
||||
self.outdir.insert(0, '~' + config.get('outdir')[len(expanduser('~')):])
|
||||
else:
|
||||
self.outdir.insert(0, config.get('outdir'))
|
||||
self.outdir.grid(row=0, padx=5, pady=5, sticky=tk.NSEW)
|
||||
self.outbutton = ttk.Button(dirframe, text=(platform=='darwin' and _('Change...') or # Folder selection button on OSX
|
||||
_('Browse...')), command=self.outbrowse) # Folder selection button on Windows
|
||||
self.outbutton.grid(row=8, column=1, padx=5, pady=(5,0), sticky=tk.NSEW)
|
||||
self.outdir = ttk.Entry(outframe, takefocus=False)
|
||||
self.outdir.insert(0, config.get('outdir'))
|
||||
self.outdir.grid(row=9, columnspan=2, padx=5, pady=5, sticky=tk.EW)
|
||||
self.outvarchanged()
|
||||
self.outbutton.grid(row=0, column=1, padx=5, pady=5, sticky=tk.NSEW)
|
||||
|
||||
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.columnconfigure(1, weight=1)
|
||||
|
||||
ttk.Label(edsmframe, text=_('Cmdr name')).grid(row=0, sticky=tk.W) # EDSM & privacy setting
|
||||
self.edsm_cmdr = ttk.Entry(edsmframe)
|
||||
self.edsm_cmdr.insert(0, config.get('edsm_cmdrname') or '')
|
||||
self.edsm_cmdr.grid(row=0, column=1, sticky=tk.NSEW)
|
||||
|
||||
ttk.Label(edsmframe, text=_('API Key')).grid(row=1, sticky=tk.W) # EDSM setting
|
||||
self.edsm_apikey = ttk.Entry(edsmframe)
|
||||
self.edsm_apikey.insert(0, config.get('edsm_apikey') or '')
|
||||
self.edsm_apikey.grid(row=1, column=1, sticky=tk.NSEW)
|
||||
|
||||
for child in edsmframe.winfo_children():
|
||||
child.grid_configure(padx=5, pady=3)
|
||||
|
||||
if platform in ['darwin','win32']:
|
||||
self.hotkey_code = config.getint('hotkey_code')
|
||||
@ -145,7 +172,6 @@ class PreferencesDialog(tk.Toplevel):
|
||||
|
||||
privacyframe = ttk.LabelFrame(frame, text=_('Privacy')) # Section heading in settings
|
||||
privacyframe.grid(padx=10, pady=10, sticky=tk.NSEW)
|
||||
privacyframe.columnconfigure(0, weight=1)
|
||||
|
||||
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)
|
||||
@ -162,6 +188,9 @@ class PreferencesDialog(tk.Toplevel):
|
||||
ttk.Button(buttonframe, text=_('OK'), command=self.apply).grid(row=0, column=1, sticky=tk.E)
|
||||
self.protocol("WM_DELETE_WINDOW", self._destroy)
|
||||
|
||||
# Selectively disable buttons depending on output settings
|
||||
self.outvarchanged()
|
||||
|
||||
# disable hotkey for the duration
|
||||
hotkeymgr.unregister()
|
||||
|
||||
@ -171,13 +200,19 @@ class PreferencesDialog(tk.Toplevel):
|
||||
#self.wait_window(self) # causes duplicate events on OSX
|
||||
|
||||
def outvarchanged(self):
|
||||
local = self.out_bpc.get() or self.out_td.get() or self.out_csv.get() or self.out_ship_eds.get() or self.out_ship_coriolis.get() or self.out_log.get()
|
||||
self.outbutton['state'] = local and tk.NORMAL or tk.DISABLED
|
||||
local = self.out_bpc.get() or self.out_td.get() or self.out_csv.get() or self.out_ship_eds.get() or self.out_ship_coriolis.get() or self.out_log_file.get()
|
||||
self.dir_label['state'] = local and tk.NORMAL or tk.DISABLED
|
||||
self.outbutton['state'] = local and tk.NORMAL or tk.DISABLED
|
||||
self.outdir['state'] = local and 'readonly' or tk.DISABLED
|
||||
|
||||
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
|
||||
self.edsm_apikey['state'] = edsm and tk.NORMAL or tk.DISABLED
|
||||
|
||||
def outbrowse(self):
|
||||
if platform != 'win32':
|
||||
d = tkFileDialog.askdirectory(parent=self, initialdir=self.outdir.get(), title=_('File location:'), mustexist=tk.TRUE)
|
||||
d = tkFileDialog.askdirectory(parent=self, initialdir=expanduser(self.outdir.get()), title=_('File location'), mustexist=tk.TRUE)
|
||||
else:
|
||||
def browsecallback(hwnd, uMsg, lParam, lpData):
|
||||
# set initial folder
|
||||
@ -186,10 +221,10 @@ class PreferencesDialog(tk.Toplevel):
|
||||
return 0
|
||||
|
||||
browseInfo = BROWSEINFO()
|
||||
browseInfo.lpszTitle = _('File location:')
|
||||
browseInfo.lpszTitle = _('File location')
|
||||
browseInfo.ulFlags = BIF_RETURNONLYFSDIRS|BIF_USENEWUI
|
||||
browseInfo.lpfn = BrowseCallbackProc(browsecallback)
|
||||
browseInfo.lParam = self.outdir.get()
|
||||
browseInfo.lParam = expanduser(self.outdir.get())
|
||||
ctypes.windll.ole32.CoInitialize(None)
|
||||
pidl = ctypes.windll.shell32.SHBrowseForFolderW(ctypes.byref(browseInfo))
|
||||
if pidl:
|
||||
@ -203,7 +238,10 @@ class PreferencesDialog(tk.Toplevel):
|
||||
if d:
|
||||
self.outdir['state'] = tk.NORMAL # must be writable to update
|
||||
self.outdir.delete(0, tk.END)
|
||||
self.outdir.insert(0, d.replace('/', sep))
|
||||
if d.startswith(expanduser('~')):
|
||||
self.outdir.insert(0, '~' + d[len(expanduser('~')):])
|
||||
else:
|
||||
self.outdir.insert(0, d)
|
||||
self.outdir['state'] = 'readonly'
|
||||
|
||||
def hotkeystart(self, event):
|
||||
@ -251,14 +289,21 @@ class PreferencesDialog(tk.Toplevel):
|
||||
credentials = (config.get('username'), config.get('password'))
|
||||
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.get() and config.OUT_LOG or 0) + (self.out_ship_coriolis.get() and config.OUT_SHIP_CORIOLIS or 0))
|
||||
config.set('outdir', self.outdir.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('outdir', expanduser(self.outdir.get()))
|
||||
|
||||
config.set('edsm_cmdrname', self.edsm_cmdr.get().strip())
|
||||
config.set('edsm_apikey', self.edsm_apikey.get().strip())
|
||||
|
||||
if platform in ['darwin','win32']:
|
||||
config.set('hotkey_code', self.hotkey_code)
|
||||
config.set('hotkey_mods', self.hotkey_mods)
|
||||
config.set('hotkey_always', int(not self.hotkey_only.get()))
|
||||
config.set('hotkey_mute', int(not self.hotkey_play.get()))
|
||||
|
||||
config.set('anonymous', self.out_anon.get())
|
||||
|
||||
self._destroy()
|
||||
if credentials != (config.get('username'), config.get('password')) and self.callback:
|
||||
self.callback()
|
||||
|
Loading…
x
Reference in New Issue
Block a user