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

Make system and station names clickable and send to EDSM and eddb respectively.

This commit is contained in:
Jonathan Harris 2015-09-05 12:23:15 +01:00
parent edcda94e0f
commit b82c186d34
8 changed files with 126 additions and 7 deletions

View File

@ -8,6 +8,8 @@ from os.path import expanduser, isdir, join
import re
import requests
from time import time, localtime, strftime
import urllib
import webbrowser
import Tkinter as tk
import ttk
@ -24,14 +26,49 @@ import eddn
import loadout
import coriolis
import flightlog
import eddb
import prefs
from config import appname, applongname, config
l10n.Translations().install()
EDDB = eddb.EDDB()
SHIPYARD_RETRY = 5 # retry pause for shipyard data [s]
class HyperlinkLabel(ttk.Label):
def __init__(self, master=None, **kw):
self.urlfn = kw.pop('urlfn', None)
ttk.Label.__init__(self, master, **kw)
self.font_n = kw.get('font', ttk.Style().lookup('TLabel', 'font'))
self.font_u = tkFont.Font(self, self.font_n)
self.font_u.configure(underline = True)
self.bind('<Enter>', self._enter)
self.bind('<Leave>', self._leave)
self.bind('<Button-1>', self._click)
# Make blue and clickable if setting non-empty text
def __setitem__(self, key, value):
if key=='text':
if self.urlfn and value:
self.configure({key: value}, foreground = 'blue', cursor = platform=='darwin' and 'pointinghand' or 'hand2')
else:
self.configure({key: value}, foreground = '', cursor = 'arrow')
else:
self.configure({key: value})
def _enter(self, event):
self.configure(font = self.font_u)
def _leave(self, event):
self.configure(font = self.font_n)
def _click(self, event):
if self.urlfn and self['text']:
webbrowser.open(self.urlfn(self['text']))
class AppWindow:
def __init__(self, master):
@ -73,8 +110,8 @@ class AppWindow:
ttk.Label(frame, text=_('Station:')).grid(row=2, column=0, sticky=tk.W) # Main window
self.cmdr = ttk.Label(frame, width=-20)
self.system = ttk.Label(frame, width=-20)
self.station = ttk.Label(frame, width=-20)
self.system = HyperlinkLabel(frame, width=-20, urlfn = self.system_url)
self.station = HyperlinkLabel(frame, width=-20, urlfn = self.station_url)
self.button = ttk.Button(frame, text=_('Update'), command=self.getandsend, default=tk.ACTIVE, state=tk.DISABLED) # Update button in main window
self.status = ttk.Label(frame, width=-25)
self.w.bind('<Return>', self.getandsend)
@ -201,7 +238,7 @@ class AppWindow:
self.cmdr['text'] = data.get('commander') and data.get('commander').get('name') or ''
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 '-'
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 '-' or ''))
config.set('querytime', querytime)
self.holdofftime = querytime + companion.holdoff
@ -295,6 +332,21 @@ class AppWindow:
self.cooldown()
def system_url(self, text):
return text and 'http://www.edsm.net/needed-distances?systemName=%s' % urllib.quote(text)
def station_url(self, text):
if text:
station_id = EDDB.station(self.system['text'], self.station['text'])
if station_id:
return 'http://eddb.io/station/%d' % station_id
system_id = EDDB.system(self.system['text'])
if system_id:
return 'http://eddb.io/system/%d' % system_id
return None
def cooldown(self):
if time() < self.holdofftime:
self.button['text'] = _('cooldown {SS}s').format(SS = int(self.holdofftime - time())) # Update button in main window

View File

@ -98,6 +98,12 @@
<Component Guid="{9DBAB544-E815-40A5-866A-391B68919344}">
<File KeyPath="yes" Source="SourceDir\select.pyd" />
</Component>
<Component Guid="*">
<File KeyPath="yes" Source="SourceDir\stations.p" />
</Component>
<Component Guid="*">
<File KeyPath="yes" Source="SourceDir\systems.p" />
</Component>
<Component Guid="{30EEAD30-A43B-4A31-A209-450A8AD17AC2}">
<File KeyPath="yes" Source="SourceDir\tcl85.dll" />
</Component>
@ -344,6 +350,8 @@
<ComponentRef Id="pyexpat.pyd" />
<ComponentRef Id="python27.dll" />
<ComponentRef Id="select.pyd" />
<ComponentRef Id="stations.p" />
<ComponentRef Id="systems.p" />
<ComponentRef Id="tcl85.dll" />
<ComponentRef Id="tk85.dll" />
<ComponentRef Id="unicodedata.pyd" />

View File

@ -9,6 +9,10 @@ This app downloads commodity market and other data from the game [Elite: Dangero
The user-interface is deliberately minimal - when you land at a station just switch to the app and press the “Update” button or press Enter to automatically download and transmit and/or save your choice of data.
Click on the system name to go to its [Elite: Dangerous Star Map](http://www.edsm.net/) (“EDSM”) entry in your web broswer.
Click on the station name to go to its [Elite: Dangerous Database](http://eddb.io/) (“eddb”) entry in your web broswer.
![Windows screenshot](img/win.png) ![Mac screenshot](img/mac.png)

View File

@ -1,7 +1,6 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
import json
import requests
from collections import defaultdict
from cookielib import LWPCookieJar
@ -193,7 +192,7 @@ class Session:
r.raise_for_status()
try:
data = json.loads(r.text)
data = r.json()
except:
self.dump(r)
raise ServerError()

53
eddb.py Executable file
View File

@ -0,0 +1,53 @@
#!/usr/bin/python
#
# eddb.io station database
#
import cPickle
from os.path import dirname, join, normpath
import sys
from sys import platform
class EDDB:
def __init__(self):
self.system_ids = cPickle.load(open(join(self.respath(), 'systems.p'), 'rb'))
self.station_ids = cPickle.load(open(join(self.respath(), 'stations.p'), 'rb'))
# system_name -> system_id
def system(self, system_name):
return self.system_ids.get(system_name, 0) # return 0 on failure (0 is not a valid id)
# (system_name, station_name) -> station_id
def station(self, system_name, station_name):
return self.station_ids.get((self.system_ids.get(system_name), station_name), 0) # return 0 on failure (0 is not a valid id)
def respath(self):
if getattr(sys, 'frozen', False):
if platform=='darwin':
return normpath(join(dirname(sys.executable), os.pardir, 'Resources'))
else:
return dirname(sys.executable)
elif __file__:
return dirname(__file__)
else:
return '.'
# build system & station database from files systems.json and stations_lite.json from http://eddb.io/api
if __name__ == "__main__":
import json
# system_name by system_id
systems = dict([(x['id'], str(x['name'])) for x in json.loads(open('systems.json').read())])
stations = json.loads(open('stations_lite.json').read())
# system_id by system_name - populated systems only
system_ids = dict([(systems[x['system_id']], x['system_id']) for x in stations])
cPickle.dump(system_ids, open('systems.p', 'wb'), protocol = cPickle.HIGHEST_PROTOCOL)
# station_id by (system_id, station_name)
station_ids = dict([((x['system_id'], str(x['name'])), x['id']) for x in stations])
cPickle.dump(station_ids, open('stations.p', 'wb'), protocol = cPickle.HIGHEST_PROTOCOL)

View File

@ -57,13 +57,14 @@ VERSION = re.search(r"^appversion\s*=\s*'(.+)'", file('config.py').read(), re.MU
SHORTVERSION = ''.join(VERSION.split('.')[:3])
if sys.platform=='darwin':
OPTIONS = { 'py2app':
{'dist_dir': dist_dir,
OPTIONS = { 'py2app':
{'dist_dir': dist_dir,
'optimize': 2,
'packages': [ 'requests' ],
'frameworks': [ 'Sparkle.framework' ],
'excludes': [ 'PIL', 'simplejson' ],
'iconfile': '%s.icns' % APPNAME,
'resources': ['stations.p', 'systems.p'],
'semi_standalone': True,
'site_packages': False,
'plist': {
@ -98,6 +99,8 @@ elif sys.platform=='win32':
DATA_FILES = [ ('', [requests.certs.where(),
'WinSparkle.dll',
'WinSparkle.pdb', # For debugging - don't include in package
'stations.p',
'systems.p',
'%s.VisualElementsManifest.xml' % APPNAME,
'%s.ico' % APPNAME ] +
[join('L10n',x) for x in os.listdir('L10n') if x.endswith('.strings')] ) ]

BIN
stations.p Normal file

Binary file not shown.

BIN
systems.p Normal file

Binary file not shown.