1
0
mirror of https://github.com/EDCD/EDMarketConnector.git synced 2025-04-18 09:57:40 +03:00

Support for running from source on Linux.

This commit is contained in:
Jonathan Harris 2015-06-04 17:09:37 +01:00
parent bb4d7498bb
commit 6cda0d9bae
8 changed files with 113 additions and 46 deletions

BIN
EDMarketConnector.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

View File

@ -25,7 +25,7 @@ class AppWindow:
def __init__(self, master): def __init__(self, master):
self.holdofftime = (config.read('querytime') or 0) + companion.holdoff self.holdofftime = config.getint('querytime') + companion.holdoff
self.session = companion.Session() self.session = companion.Session()
self.w = master self.w = master
@ -33,6 +33,13 @@ class AppWindow:
self.w.rowconfigure(0, weight=1) self.w.rowconfigure(0, weight=1)
self.w.columnconfigure(0, weight=1) self.w.columnconfigure(0, weight=1)
if platform == 'win32':
self.w.wm_iconbitmap(default='EDMarketConnector.ico')
elif platform == 'linux2':
from PIL import Image, ImageTk
icon = ImageTk.PhotoImage(Image.open("EDMarketConnector.png"))
root.tk.call('wm', 'iconphoto', root, '-default', icon)
frame = ttk.Frame(self.w) frame = ttk.Frame(self.w)
frame.grid(sticky=tk.NSEW) frame.grid(sticky=tk.NSEW)
frame.columnconfigure(1, weight=1) frame.columnconfigure(1, weight=1)
@ -74,20 +81,18 @@ class AppWindow:
menubar.add_cascade(label="File", menu=file_menu) menubar.add_cascade(label="File", menu=file_menu)
root.protocol("WM_DELETE_WINDOW", self.onexit) root.protocol("WM_DELETE_WINDOW", self.onexit)
if platform=='win32':
self.w.wm_iconbitmap(default='EDMarketConnector.ico')
# update geometry # update geometry
if config.read('geometry'): if config.get('geometry'):
self.w.geometry(config.read('geometry')) self.w.geometry(config.get('geometry'))
self.w.update_idletasks() self.w.update_idletasks()
self.w.wait_visibility() self.w.wait_visibility()
(w, h) = (self.w.winfo_width(), self.w.winfo_height()) (w, h) = (self.w.winfo_width(), self.w.winfo_height())
self.w.minsize(w, h) # Minimum size = initial size self.w.minsize(w, h) # Minimum size = initial size
self.w.maxsize(-1, h) # Maximum height = initial height if platform != 'linux2': # update_idletasks() doesn't allow for the menubar on Linux
self.w.maxsize(-1, h) # Maximum height = initial height
# First run # First run
if not config.read('username') or not config.read('password'): if not config.get('username') or not config.get('password'):
prefs.PreferencesDialog(self.w, self.login) prefs.PreferencesDialog(self.w, self.login)
else: else:
self.login() self.login()
@ -98,7 +103,7 @@ class AppWindow:
self.button['state'] = tk.DISABLED self.button['state'] = tk.DISABLED
self.w.update_idletasks() self.w.update_idletasks()
try: try:
self.session.login(config.read('username'), config.read('password')) self.session.login(config.get('username'), config.get('password'))
self.status['text'] = '' self.status['text'] = ''
except companion.VerificationRequired: except companion.VerificationRequired:
# don't worry about authentication now # don't worry about authentication now
@ -134,7 +139,7 @@ class AppWindow:
self.system['text'] = data.get('lastSystem') and data.get('lastSystem').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 '-'
config.write('querytime', querytime) config.set('querytime', querytime)
self.holdofftime = querytime + companion.holdoff self.holdofftime = querytime + companion.holdoff
# Validation # Validation
@ -147,16 +152,16 @@ class AppWindow:
elif not data.get('lastStarport') or not data['lastStarport'].get('commodities'): elif not data.get('lastStarport') or not data['lastStarport'].get('commodities'):
raise Exception("Station doesn't have a market!") raise Exception("Station doesn't have a market!")
if config.read('output') & config.OUT_CSV: if config.getint('output') & config.OUT_CSV:
bpc.export(data, True) bpc.export(data, True)
if config.read('output') & config.OUT_TD: if config.getint('output') & config.OUT_TD:
td.export(data) td.export(data)
if config.read('output') & config.OUT_BPC: if config.getint('output') & config.OUT_BPC:
bpc.export(data, False) bpc.export(data, False)
if config.read('output') & config.OUT_EDDN: if config.getint('output') & config.OUT_EDDN:
eddn.export(data, self.setstatus) eddn.export(data, self.setstatus)
except companion.VerificationRequired: except companion.VerificationRequired:
@ -185,7 +190,7 @@ class AppWindow:
self.w.update_idletasks() self.w.update_idletasks()
def onexit(self): def onexit(self):
config.write('geometry', '+{1}+{2}'.format(*self.w.geometry().split('+'))) config.set('geometry', '+{1}+{2}'.format(*self.w.geometry().split('+')))
config.close() config.close()
self.session.close() self.session.close()
self.w.destroy() self.w.destroy()

4
bpc.py
View File

@ -10,9 +10,9 @@ from companion import commoditymap, bracketmap
def export(data, csv=False): def export(data, csv=False):
querytime = config.read('querytime') or int(time.time()) querytime = config.getint('querytime') or int(time.time())
filename = join(config.read('outdir'), '%s.%s.%s.%s' % (data['lastSystem']['name'].strip(), data['lastStarport']['name'].strip(), time.strftime('%Y-%m-%dT%H.%M.%S', time.localtime(querytime)), csv and 'csv' or 'bpc')) filename = join(config.get('outdir'), '%s.%s.%s.%s' % (data['lastSystem']['name'].strip(), data['lastStarport']['name'].strip(), time.strftime('%Y-%m-%dT%H.%M.%S', time.localtime(querytime)), csv and 'csv' or 'bpc'))
timestamp = time.strftime('%Y-%m-%dT%H:%M:%S', time.gmtime(querytime)) timestamp = time.strftime('%Y-%m-%dT%H:%M:%S', time.gmtime(querytime))
if csv: if csv:

View File

@ -1,11 +1,18 @@
import sys import sys
from os import mkdir from os import getenv, makedirs, mkdir
from os.path import basename, isdir, join from os.path import expanduser, dirname, isdir, join
from sys import platform from sys import platform
if platform=='win32': if platform=='darwin':
from Foundation import NSBundle, NSUserDefaults, NSSearchPathForDirectoriesInDomains, NSApplicationSupportDirectory, NSDocumentDirectory, NSLibraryDirectory, NSUserDomainMask
elif platform=='win32':
import ctypes.wintypes
import numbers import numbers
import _winreg import _winreg
elif platform=='linux2':
import codecs
# requires python-iniparse package - ConfigParser that ships with Python < 3.2 doesn't support unicode
from iniparse import RawConfigParser
appname = 'EDMarketConnector' appname = 'EDMarketConnector'
@ -23,8 +30,6 @@ class Config:
if platform=='darwin': if platform=='darwin':
def __init__(self): def __init__(self):
from Foundation import NSBundle, NSUserDefaults, NSSearchPathForDirectoriesInDomains, NSApplicationSupportDirectory, NSDocumentDirectory, NSLibraryDirectory, NSUserDomainMask
self.app_dir = join(NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, True)[0], appname) self.app_dir = join(NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, True)[0], appname)
if not isdir(self.app_dir): if not isdir(self.app_dir):
mkdir(self.app_dir) mkdir(self.app_dir)
@ -35,13 +40,19 @@ class Config:
self.settings = dict(settings) self.settings = dict(settings)
# Check out_dir exists # Check out_dir exists
if not self.read('outdir') or not isdir(self.read('outdir')): if not self.get('outdir') or not isdir(self.get('outdir')):
self.write('outdir', NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, True)[0]) self.set('outdir', NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, True)[0])
def read(self, key): def get(self, key):
return self.settings.get(key) return self.settings.get(key)
def write(self, key, val): def getint(self, key):
try:
return int(self.settings.get(key, 0)) # should already be int, but check by casting
except:
return 0
def set(self, key, val):
self.settings[key] = val self.settings[key] = val
def close(self): def close(self):
@ -52,7 +63,6 @@ class Config:
elif platform=='win32': elif platform=='win32':
def __init__(self): def __init__(self):
import ctypes.wintypes
CSIDL_PERSONAL = 0x0005 CSIDL_PERSONAL = 0x0005
CSIDL_LOCAL_APPDATA = 0x001C CSIDL_LOCAL_APPDATA = 0x001C
buf = ctypes.create_unicode_buffer(ctypes.wintypes.MAX_PATH) buf = ctypes.create_unicode_buffer(ctypes.wintypes.MAX_PATH)
@ -63,17 +73,23 @@ class Config:
self.handle = _winreg.CreateKey(_winreg.HKEY_CURRENT_USER, r'Software\%s' % appname) self.handle = _winreg.CreateKey(_winreg.HKEY_CURRENT_USER, r'Software\%s' % appname)
if not self.read('outdir') or not isdir(self.read('outdir')): if not self.get('outdir') or not isdir(self.get('outdir')):
ctypes.windll.shell32.SHGetSpecialFolderPathW(0, buf, CSIDL_PERSONAL, 0) ctypes.windll.shell32.SHGetSpecialFolderPathW(0, buf, CSIDL_PERSONAL, 0)
self.write('outdir', buf.value) self.set('outdir', buf.value)
def read(self, key): def get(self, key):
try: try:
return _winreg.QueryValueEx(self.handle, key)[0] return _winreg.QueryValueEx(self.handle, key)[0]
except: except:
return None return None
def write(self, key, val): def getint(self, key):
try:
return int(_winreg.QueryValueEx(self.handle, key)[0]) # should already be int, but check by casting
except:
return 0
def set(self, key, val):
if isinstance(val, basestring): if isinstance(val, basestring):
_winreg.SetValueEx(self.handle, key, 0, _winreg.REG_SZ, val) _winreg.SetValueEx(self.handle, key, 0, _winreg.REG_SZ, val)
elif isinstance(val, numbers.Integral): elif isinstance(val, numbers.Integral):
@ -85,7 +101,51 @@ class Config:
_winreg.CloseKey(self.handle) _winreg.CloseKey(self.handle)
self.handle = None self.handle = None
else: # unix elif platform=='linux2':
def __init__(self):
# http://standards.freedesktop.org/basedir-spec/latest/ar01s03.html
self.app_dir = join(getenv('XDG_DATA_HOME', expanduser('~/.local/share')), appname)
if not isdir(self.app_dir):
makedirs(self.app_dir)
self.filename = join(getenv('XDG_CONFIG_HOME', expanduser('~/.config')), appname, '%s.ini' % appname)
if not isdir(dirname(self.filename)):
makedirs(dirname(self.filename))
self.config = RawConfigParser()
try:
self.config.readfp(codecs.open(self.filename, 'r', 'utf-8'))
# XXX handle missing?
except:
self.config.add_section('DEFAULT')
if not self.get('outdir') or not isdir(self.get('outdir')):
self.set('outdir', expanduser('~'))
def set(self, key, val):
self.config.set('DEFAULT', key, val)
def get(self, key):
try:
return self.config.get('DEFAULT', key) # all values are stored as strings
except:
return None
def getint(self, key):
try:
return int(self.config.get('DEFAULT', key)) # all values are stored as strings
except:
return 0
def close(self):
h = codecs.open(self.filename, 'w', 'utf-8')
h.write(unicode(self.config.data))
h.close()
self.config = None
else: # ???
def __init__(self): def __init__(self):
raise NotImplementedError('Implement me') raise NotImplementedError('Implement me')

View File

@ -17,7 +17,7 @@ def export(data, callback):
callback('Sending data to EDDN...') callback('Sending data to EDDN...')
querytime = config.read('querytime') or int(time.time()) querytime = config.getint('querytime') or int(time.time())
header = { 'softwareName': '%s [%s]' % (applongname, platform=='darwin' and "Mac OS" or system()), header = { 'softwareName': '%s [%s]' % (applongname, platform=='darwin' and "Mac OS" or system()),
'softwareVersion': appversion, 'softwareVersion': appversion,

View File

@ -46,11 +46,11 @@ class PreferencesDialog(tk.Toplevel):
ttk.Label(credframe, text="Password").grid(row=2, sticky=tk.W) ttk.Label(credframe, text="Password").grid(row=2, sticky=tk.W)
self.username = ttk.Entry(credframe) self.username = ttk.Entry(credframe)
self.username.insert(0, config.read('username') or '') self.username.insert(0, config.get('username') or '')
self.username.grid(row=1, column=1, sticky=tk.NSEW) self.username.grid(row=1, column=1, sticky=tk.NSEW)
self.username.focus_set() self.username.focus_set()
self.password = ttk.Entry(credframe, show=u'') self.password = ttk.Entry(credframe, show=u'')
self.password.insert(0, config.read('password') or '') self.password.insert(0, config.get('password') or '')
self.password.grid(row=2, column=1, sticky=tk.NSEW) self.password.grid(row=2, column=1, sticky=tk.NSEW)
for child in credframe.winfo_children(): for child in credframe.winfo_children():
@ -60,7 +60,7 @@ class PreferencesDialog(tk.Toplevel):
outframe.grid(padx=10, pady=10, sticky=tk.NSEW) outframe.grid(padx=10, pady=10, sticky=tk.NSEW)
outframe.columnconfigure(0, weight=1) outframe.columnconfigure(0, weight=1)
output = config.read('output') or config.OUT_EDDN output = config.getint('output') or config.OUT_EDDN
ttk.Label(outframe, text="Please choose where you want the market data saved").grid(row=0, columnspan=2, padx=5, pady=3, sticky=tk.W) ttk.Label(outframe, text="Please choose where you want the market data saved").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) self.out_eddn= tk.IntVar(value = (output & config.OUT_EDDN) and 1 or 0)
ttk.Checkbutton(outframe, text="Online to the Elite Dangerous Data Network (EDDN)", variable=self.out_eddn).grid(row=1, columnspan=2, padx=5, sticky=tk.W) ttk.Checkbutton(outframe, text="Online to the Elite Dangerous Data Network (EDDN)", variable=self.out_eddn).grid(row=1, columnspan=2, padx=5, sticky=tk.W)
@ -74,7 +74,7 @@ class PreferencesDialog(tk.Toplevel):
self.outbutton = ttk.Button(outframe, text=(platform=='darwin' and 'Change...' or 'Browse...'), command=self.outbrowse) self.outbutton = ttk.Button(outframe, text=(platform=='darwin' and 'Change...' or 'Browse...'), command=self.outbrowse)
self.outbutton.grid(row=5, column=1, padx=5, pady=(5,0), sticky=tk.NSEW) self.outbutton.grid(row=5, column=1, padx=5, pady=(5,0), sticky=tk.NSEW)
self.outdir = ttk.Entry(outframe) self.outdir = ttk.Entry(outframe)
self.outdir.insert(0, config.read('outdir')) self.outdir.insert(0, config.get('outdir'))
self.outdir.grid(row=6, columnspan=2, padx=5, pady=5, sticky=tk.EW) self.outdir.grid(row=6, columnspan=2, padx=5, pady=5, sticky=tk.EW)
self.outvarchanged() self.outvarchanged()
@ -106,13 +106,13 @@ class PreferencesDialog(tk.Toplevel):
self.outdir['state'] = 'readonly' self.outdir['state'] = 'readonly'
def apply(self): def apply(self):
credentials = (config.read('username'), config.read('password')) credentials = (config.get('username'), config.get('password'))
config.write('username', self.username.get().strip()) config.set('username', self.username.get().strip())
config.write('password', self.password.get().strip()) config.set('password', self.password.get().strip())
config.write('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)) 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))
config.write('outdir', self.outdir.get().strip()) config.set('outdir', self.outdir.get().strip())
self.destroy() self.destroy()
if credentials != (config.read('username'), config.read('password')) and self.callback: if credentials != (config.get('username'), config.get('password')) and self.callback:
self.callback() self.callback()

View File

@ -54,6 +54,7 @@ SHORTVERSION = ''.join(VERSION.split('.')[:3])
PY2APP_OPTIONS = {'dist_dir': dist_dir, PY2APP_OPTIONS = {'dist_dir': dist_dir,
'optimize': 2, 'optimize': 2,
'packages': [ 'requests' ], 'packages': [ 'requests' ],
'excludes': [ 'PIL' ],
'iconfile': '%s.icns' % APPNAME, 'iconfile': '%s.icns' % APPNAME,
'semi_standalone': True, 'semi_standalone': True,
'site_packages': False, 'site_packages': False,
@ -71,6 +72,7 @@ PY2APP_OPTIONS = {'dist_dir': dist_dir,
PY2EXE_OPTIONS = {'dist_dir': dist_dir, PY2EXE_OPTIONS = {'dist_dir': dist_dir,
'optimize': 2, 'optimize': 2,
'packages': [ 'requests' ], 'packages': [ 'requests' ],
'excludes': [ 'PIL' ],
} }
if sys.platform=='win32': if sys.platform=='win32':

4
td.py
View File

@ -13,9 +13,9 @@ from companion import categorymap, commoditymap, bracketmap
def export(data): def export(data):
querytime = config.read('querytime') or int(time.time()) querytime = config.getint('querytime') or int(time.time())
filename = join(config.read('outdir'), '%s.%s.%s.prices' % (data['lastSystem']['name'].strip(), data['lastStarport']['name'].strip(), time.strftime('%Y-%m-%dT%H.%M.%S', time.localtime(querytime)))) filename = join(config.get('outdir'), '%s.%s.%s.prices' % (data['lastSystem']['name'].strip(), data['lastStarport']['name'].strip(), time.strftime('%Y-%m-%dT%H.%M.%S', time.localtime(querytime))))
timestamp = time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(querytime)) timestamp = time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(querytime))