mirror of
https://github.com/norohind/EDMC_SpanshRouter.git
synced 2025-04-22 03:50:28 +03:00
Copied modules outside SpanshRouter folder.
Python 3 seems to be having issues importing some modules.
This commit is contained in:
parent
5847715897
commit
62e55ee0be
206
AutoCompleter.py
Normal file
206
AutoCompleter.py
Normal file
@ -0,0 +1,206 @@
|
||||
import threading
|
||||
import json
|
||||
import os
|
||||
import requests
|
||||
import traceback
|
||||
from time import sleep
|
||||
from PlaceHolder import PlaceHolder
|
||||
import sys
|
||||
|
||||
try:
|
||||
# Python 2
|
||||
from Tkinter import *
|
||||
import ttk
|
||||
except ModuleNotFoundError:
|
||||
# Python 3
|
||||
import tkinter as tk
|
||||
from tkinter import *
|
||||
|
||||
is_py2 = sys.version[0] == '2'
|
||||
if is_py2:
|
||||
import Queue as queue
|
||||
else:
|
||||
import queue as queue
|
||||
|
||||
|
||||
class AutoCompleter(Entry, PlaceHolder):
|
||||
def __init__(self, parent, placeholder, **kw):
|
||||
Entry.__init__(self, parent, **kw)
|
||||
self.var = self["textvariable"] = StringVar()
|
||||
self.var.traceid = self.var.trace('w', self.changed)
|
||||
|
||||
self.parent = parent
|
||||
|
||||
self.lb = Listbox(self.parent, selectmode=SINGLE, **kw)
|
||||
self.lb_up = False
|
||||
self.has_selected = False
|
||||
self.queue = Queue.Queue()
|
||||
|
||||
PlaceHolder.__init__(self, placeholder)
|
||||
|
||||
# Create right click menu
|
||||
self.menu = Menu(self.parent, tearoff=0)
|
||||
self.menu.add_command(label="Cut")
|
||||
self.menu.add_command(label="Copy")
|
||||
self.menu.add_command(label="Paste")
|
||||
|
||||
self.bind("<Any-Key>", self.keypressed)
|
||||
self.lb.bind("<Any-Key>", self.keypressed)
|
||||
self.bind('<Control-KeyRelease-a>', self.select_all)
|
||||
self.bind('<Button-3>', self.show_menu)
|
||||
self.lb.bind("<Double-Button-1>", self.selection)
|
||||
self.bind("<FocusOut>", self.ac_foc_out)
|
||||
self.lb.bind("<FocusOut>", self.ac_foc_out)
|
||||
|
||||
self.update_me()
|
||||
|
||||
def ac_foc_out(self, event):
|
||||
x,y = self.parent.winfo_pointerxy()
|
||||
widget_under_cursor = self.parent.winfo_containing(x,y)
|
||||
if widget_under_cursor != self.lb and widget_under_cursor != self:
|
||||
self.foc_out()
|
||||
self.hide_list()
|
||||
|
||||
def show_menu(self, e):
|
||||
self.foc_in()
|
||||
w = e.widget
|
||||
self.menu.entryconfigure("Cut",
|
||||
command=lambda: w.event_generate("<<Cut>>"))
|
||||
self.menu.entryconfigure("Copy",
|
||||
command=lambda: w.event_generate("<<Copy>>"))
|
||||
self.menu.entryconfigure("Paste",
|
||||
command=lambda: w.event_generate("<<Paste>>"))
|
||||
self.menu.tk.call("tk_popup", self.menu, e.x_root, e.y_root)
|
||||
|
||||
def keypressed(self, event):
|
||||
key=event.keysym
|
||||
if key == 'Down':
|
||||
self.down(event.widget.widgetName)
|
||||
elif key == 'Up':
|
||||
self.up(event.widget.widgetName)
|
||||
elif key in ['Return', 'Right']:
|
||||
if self.lb_up:
|
||||
self.selection()
|
||||
elif key == 'Escape' and self.lb_up:
|
||||
self.hide_list()
|
||||
|
||||
def select_all(self, event):
|
||||
event.widget.event_generate('<<SelectAll>>')
|
||||
|
||||
def changed(self, name, index, mode):
|
||||
self.set_default_style()
|
||||
value = self.var.get()
|
||||
if value.__len__() < 3 and self.lb_up or self.has_selected:
|
||||
self.hide_list()
|
||||
self.has_selected = False
|
||||
else:
|
||||
t = threading.Thread(target=self.query_systems, args=[value])
|
||||
t.start()
|
||||
|
||||
def selection(self, event=None):
|
||||
if self.lb_up:
|
||||
self.has_selected = True
|
||||
self.var.set(self.lb.get(ACTIVE))
|
||||
self.hide_list()
|
||||
self.icursor(END)
|
||||
|
||||
def up(self, widget):
|
||||
if self.lb_up:
|
||||
if self.lb.curselection() == ():
|
||||
index = '0'
|
||||
else:
|
||||
index = self.lb.curselection()[0]
|
||||
if index != '0':
|
||||
self.lb.selection_clear(first=index)
|
||||
index = str(int(index)-1)
|
||||
self.lb.selection_set(first=index)
|
||||
if widget != "listbox":
|
||||
self.lb.activate(index)
|
||||
|
||||
def down(self, widget):
|
||||
if self.lb_up:
|
||||
if self.lb.curselection() == ():
|
||||
index = '0'
|
||||
else:
|
||||
index = self.lb.curselection()[0]
|
||||
if int(index+1) != END:
|
||||
self.lb.selection_clear(first=index)
|
||||
index = str(int(index+1))
|
||||
|
||||
self.lb.selection_set(first=index)
|
||||
if widget != "listbox":
|
||||
self.lb.activate(index)
|
||||
else:
|
||||
self.query_systems()
|
||||
|
||||
def show_results(self, results):
|
||||
if results:
|
||||
self.lb.delete(0, END)
|
||||
for w in results:
|
||||
self.lb.insert(END,w)
|
||||
|
||||
self.show_list(len(results))
|
||||
else:
|
||||
if self.lb_up:
|
||||
self.hide_list()
|
||||
|
||||
def show_list(self, height):
|
||||
self.lb["height"] = height
|
||||
if not self.lb_up:
|
||||
info = self.grid_info()
|
||||
if info:
|
||||
self.lb.grid(row=int(info["row"])+1, columnspan=2)
|
||||
self.lb_up = True
|
||||
|
||||
def hide_list(self):
|
||||
if self.lb_up:
|
||||
self.lb.grid_remove()
|
||||
self.lb_up = False
|
||||
|
||||
def query_systems(self, inp):
|
||||
inp = inp.strip()
|
||||
if inp != self.placeholder and inp.__len__() >= 3:
|
||||
url = "https://spansh.co.uk/api/systems?"
|
||||
try:
|
||||
results = requests.get(url,
|
||||
params={'q': inp},
|
||||
headers={'User-Agent': "EDMC_SpanshRouter 1.0"},
|
||||
timeout=3)
|
||||
|
||||
lista = json.loads(results.content)
|
||||
if lista:
|
||||
self.write(lista)
|
||||
except:
|
||||
exc_type, exc_value, exc_traceback = sys.exc_info()
|
||||
lines = traceback.format_exception(exc_type, exc_value, exc_traceback)
|
||||
sys.stderr.write(''.join('!! ' + line for line in lines))
|
||||
|
||||
def write(self, lista):
|
||||
self.queue.put(lista)
|
||||
|
||||
def clear(self):
|
||||
self.queue.put(None)
|
||||
|
||||
def update_me(self):
|
||||
try:
|
||||
while 1:
|
||||
lista = self.queue.get_nowait()
|
||||
self.show_results(lista)
|
||||
self.update_idletasks()
|
||||
except Queue.Empty:
|
||||
pass
|
||||
self.after(100, self.update_me)
|
||||
|
||||
def set_text(self, text):
|
||||
self.var.trace_vdelete("w", self.var.traceid)
|
||||
self.set_default_style()
|
||||
self.delete(0, END)
|
||||
self.insert(0, text)
|
||||
self.var.traceid = self.var.trace('w', self.changed)
|
||||
|
||||
if __name__ == '__main__':
|
||||
root = Tk()
|
||||
|
||||
widget = AutoCompleter(root, "Test")
|
||||
widget.grid(row=0)
|
||||
root.mainloop()
|
51
PlaceHolder.py
Normal file
51
PlaceHolder.py
Normal file
@ -0,0 +1,51 @@
|
||||
from config import config
|
||||
try:
|
||||
# Python 2
|
||||
from Tkinter import END
|
||||
except ModuleNotFoundError:
|
||||
# Python 3
|
||||
import tkinter as tk
|
||||
from tkinter import *
|
||||
|
||||
class PlaceHolder():
|
||||
def __init__(self, placeholder, **kw):
|
||||
self.placeholder = placeholder
|
||||
self.placeholder_color = "grey"
|
||||
|
||||
self.bind("<FocusIn>", self.foc_in)
|
||||
self.bind("<FocusOut>", self.foc_out)
|
||||
|
||||
self.put_placeholder()
|
||||
|
||||
def put_placeholder(self):
|
||||
self['fg'] = self.placeholder_color
|
||||
if self.get() != self.placeholder:
|
||||
self.set_text(self.placeholder)
|
||||
|
||||
def set_text(self, text):
|
||||
self.set_default_style()
|
||||
self.delete(0, END)
|
||||
self.insert(0, text)
|
||||
|
||||
def force_placeholder_color(self):
|
||||
self['fg'] = self.placeholder_color
|
||||
|
||||
def set_default_style(self):
|
||||
theme = config.getint('theme')
|
||||
self['fg'] = config.get('dark_text') if theme else "black"
|
||||
|
||||
def set_error_style(self, error=True):
|
||||
if error:
|
||||
self['fg'] = "red"
|
||||
else:
|
||||
self.set_default_style()
|
||||
|
||||
def foc_in(self, *args):
|
||||
if self['fg'] == "red" or self['fg'] == self.placeholder_color:
|
||||
self.set_default_style()
|
||||
if self.get() == self.placeholder:
|
||||
self.delete('0', 'end')
|
||||
|
||||
def foc_out(self, *args):
|
||||
if not self.get():
|
||||
self.put_placeholder()
|
15
PlaceHolderEntry.py
Normal file
15
PlaceHolderEntry.py
Normal file
@ -0,0 +1,15 @@
|
||||
from PlaceHolder import PlaceHolder
|
||||
|
||||
try:
|
||||
# Python 2
|
||||
from Tkinter import *
|
||||
except ModuleNotFoundError:
|
||||
# Python 3
|
||||
import tkinter as tk
|
||||
from tkinter import *
|
||||
|
||||
class PlaceHolderEntry(Entry, PlaceHolder):
|
||||
def __init__(self, parent, placeholder, **kw):
|
||||
Entry.__init__(self, parent, **kw)
|
||||
self.var = self["textvariable"] = StringVar()
|
||||
PlaceHolder.__init__(self, placeholder)
|
591
SpanshRouter.py
Normal file
591
SpanshRouter.py
Normal file
@ -0,0 +1,591 @@
|
||||
import os
|
||||
import sys
|
||||
import traceback
|
||||
import csv
|
||||
import subprocess
|
||||
import webbrowser
|
||||
import json
|
||||
import re
|
||||
import requests
|
||||
from time import sleep
|
||||
from monitor import monitor
|
||||
from . import AutoCompleter
|
||||
from . import PlaceHolderEntry
|
||||
from .updater import SpanshUpdater
|
||||
|
||||
try:
|
||||
# Python 2
|
||||
from Tkinter import *
|
||||
import tkFileDialog as filedialog
|
||||
import tkMessageBox as confirmDialog
|
||||
import ttk
|
||||
except ModuleNotFoundError:
|
||||
# Python 3
|
||||
import tkinter as tk
|
||||
from tkinter import *
|
||||
import tkinter.filedialog as filedialog
|
||||
import tkinter.messagebox as confirmDialog
|
||||
|
||||
class SpanshRouter():
|
||||
def __init__(self, plugin_dir):
|
||||
version_file = os.path.join(plugin_dir, "version.json")
|
||||
with open(version_file, 'r') as version_fd:
|
||||
self.plugin_version = version_fd.read()
|
||||
|
||||
self.update_available = False
|
||||
self.next_stop = "No route planned"
|
||||
self.route = []
|
||||
self.next_wp_label = "Next waypoint: "
|
||||
self.jumpcountlbl_txt = "Estimated jumps left: "
|
||||
self.parent = None
|
||||
self.plugin_dir = plugin_dir
|
||||
self.save_route_path = os.path.join(plugin_dir, 'route.csv')
|
||||
self.offset_file_path = os.path.join(plugin_dir, 'offset')
|
||||
self.offset = 0
|
||||
self.jumps_left = 0
|
||||
self.error_txt = tk.StringVar()
|
||||
self.plot_error = "Error while trying to plot a route, please try again."
|
||||
self.system_header = "System Name"
|
||||
self.jumps_header = "Jumps"
|
||||
|
||||
# -- GUI part --
|
||||
def init_gui(self, parent):
|
||||
self.parent = parent
|
||||
parentwidth = parent.winfo_width()
|
||||
self.frame = tk.Frame(parent, borderwidth=2)
|
||||
self.frame.grid(sticky=tk.NSEW, columnspan=2)
|
||||
|
||||
# Route info
|
||||
self.waypoint_prev_btn = tk.Button(self.frame, text="^", command=self.goto_prev_waypoint)
|
||||
self.waypoint_btn = tk.Button(self.frame, text=self.next_wp_label + self.next_stop, command=self.copy_waypoint)
|
||||
self.waypoint_next_btn = tk.Button(self.frame, text="v", command=self.goto_next_waypoint)
|
||||
self.jumpcounttxt_lbl = tk.Label(self.frame, text=self.jumpcountlbl_txt + str(self.jumps_left))
|
||||
self.error_lbl = tk.Label(self.frame, textvariable=self.error_txt)
|
||||
|
||||
# Plotting GUI
|
||||
self.source_ac = AutoCompleter(self.frame, "Source System", width=30)
|
||||
self.dest_ac = AutoCompleter(self.frame, "Destination System", width=30)
|
||||
self.range_entry = PlaceHolderEntry(self.frame, "Range (LY)", width=10)
|
||||
self.efficiency_slider = tk.Scale(self.frame, from_=1, to=100, orient=tk.HORIZONTAL, label="Efficiency (%)")
|
||||
self.efficiency_slider.set(60)
|
||||
self.plot_gui_btn = tk.Button(self.frame, text="Plot route", command=self.show_plot_gui)
|
||||
self.plot_route_btn = tk.Button(self.frame, text="Calculate", command=self.plot_route)
|
||||
self.cancel_plot = tk.Button(self.frame, text="Cancel", command=lambda: self.show_plot_gui(False))
|
||||
|
||||
self.csv_route_btn = tk.Button(self.frame, text="Import file", command=self.plot_file)
|
||||
self.clear_route_btn = tk.Button(self.frame, text="Clear route", command=self.clear_route)
|
||||
|
||||
row = 0
|
||||
self.waypoint_prev_btn.grid(row=row, columnspan=2)
|
||||
row += 1
|
||||
self.waypoint_btn.grid(row=row, columnspan=2)
|
||||
row += 1
|
||||
self.waypoint_next_btn.grid(row=row, columnspan=2)
|
||||
row += 1
|
||||
self.source_ac.grid(row=row,columnspan=2, pady=(10,0)) # The AutoCompleter takes two rows to show the list when needed, so we skip one
|
||||
row += 2
|
||||
self.dest_ac.grid(row=row,columnspan=2, pady=(10,0))
|
||||
row += 2
|
||||
self.range_entry.grid(row=row, pady=10, sticky=tk.W)
|
||||
row += 1
|
||||
self.efficiency_slider.grid(row=row, pady=10, columnspan=2, sticky=tk.EW)
|
||||
row += 1
|
||||
self.csv_route_btn.grid(row=row, pady=10, padx=0)
|
||||
self.plot_route_btn.grid(row=row, pady=10, padx=0)
|
||||
self.plot_gui_btn.grid(row=row, column=1, pady=10, padx=5, sticky=tk.W)
|
||||
self.cancel_plot.grid(row=row, column=1, pady=10, padx=5, sticky=tk.E)
|
||||
row += 1
|
||||
self.clear_route_btn.grid(row=row,column=1)
|
||||
row += 1
|
||||
self.jumpcounttxt_lbl.grid(row=row, pady=5, sticky=tk.W)
|
||||
row += 1
|
||||
self.error_lbl.grid(row=row, columnspan=2)
|
||||
self.error_lbl.grid_remove()
|
||||
row += 1
|
||||
|
||||
# Check if we're having a valid range on the fly
|
||||
self.range_entry.var.trace('w', self.check_range)
|
||||
|
||||
self.show_plot_gui(False)
|
||||
|
||||
if not self.route.__len__() > 0:
|
||||
self.waypoint_prev_btn.grid_remove()
|
||||
self.waypoint_btn.grid_remove()
|
||||
self.waypoint_next_btn.grid_remove()
|
||||
self.jumpcounttxt_lbl.grid_remove()
|
||||
self.clear_route_btn.grid_remove()
|
||||
|
||||
if self.update_available:
|
||||
update_txt = "New Spansh update available!\n"
|
||||
update_txt += "If you choose to install it, you will have to restart EDMC for it to take effect.\n\n"
|
||||
update_txt += self.spansh_updater.changelogs
|
||||
update_txt += "\n\nInstall?"
|
||||
install_update = confirmDialog.askyesno("SpanshRouter", update_txt)
|
||||
|
||||
if install_update:
|
||||
confirmDialog.showinfo("SpanshRouter", "The update will be installed as soon as you quit EDMC.")
|
||||
else:
|
||||
self.update_available = False
|
||||
|
||||
self.update_gui()
|
||||
|
||||
return self.frame
|
||||
|
||||
def show_plot_gui(self, show=True):
|
||||
if show:
|
||||
self.waypoint_prev_btn.grid_remove()
|
||||
self.waypoint_btn.grid_remove()
|
||||
self.waypoint_next_btn.grid_remove()
|
||||
self.jumpcounttxt_lbl.grid_remove()
|
||||
self.clear_route_btn.grid_remove()
|
||||
|
||||
self.plot_gui_btn.grid_remove()
|
||||
self.csv_route_btn.grid_remove()
|
||||
self.source_ac.grid()
|
||||
self.source_ac.set_text(monitor.system)
|
||||
self.dest_ac.grid()
|
||||
self.range_entry.grid()
|
||||
self.efficiency_slider.grid()
|
||||
self.plot_route_btn.grid()
|
||||
self.cancel_plot.grid()
|
||||
|
||||
# Workaround because EDMC keeps switching the placeholder to bright white
|
||||
if self.source_ac.get() == self.source_ac.placeholder:
|
||||
self.source_ac.force_placeholder_color()
|
||||
if self.dest_ac.get() == self.dest_ac.placeholder:
|
||||
self.dest_ac.force_placeholder_color()
|
||||
if self.range_entry.get() == self.range_entry.placeholder:
|
||||
self.range_entry.force_placeholder_color()
|
||||
self.show_route_gui(False)
|
||||
|
||||
else:
|
||||
if len(self.source_ac.var.get()) == 0:
|
||||
self.source_ac.put_placeholder()
|
||||
if len(self.dest_ac.var.get()) == 0:
|
||||
self.dest_ac.put_placeholder()
|
||||
self.source_ac.grid_remove()
|
||||
self.dest_ac.grid_remove()
|
||||
self.range_entry.grid_remove()
|
||||
self.efficiency_slider.grid_remove()
|
||||
self.plot_gui_btn.grid_remove()
|
||||
self.plot_route_btn.grid_remove()
|
||||
self.cancel_plot.grid_remove()
|
||||
self.plot_gui_btn.grid()
|
||||
self.csv_route_btn.grid()
|
||||
self.show_route_gui(True)
|
||||
|
||||
def set_source_ac(self, text):
|
||||
self.source_ac.delete(0, tk.END)
|
||||
self.source_ac.insert(0, text)
|
||||
self.source_ac.set_default_style()
|
||||
|
||||
def show_route_gui(self, show):
|
||||
self.hide_error()
|
||||
if not show or not self.route.__len__() > 0:
|
||||
self.waypoint_prev_btn.grid_remove()
|
||||
self.waypoint_btn.grid_remove()
|
||||
self.waypoint_next_btn.grid_remove()
|
||||
self.jumpcounttxt_lbl.grid_remove()
|
||||
self.clear_route_btn.grid_remove()
|
||||
else:
|
||||
self.waypoint_btn["text"] = self.next_wp_label + self.next_stop
|
||||
if self.jumps_left > 0:
|
||||
self.jumpcounttxt_lbl["text"] = self.jumpcountlbl_txt + str(self.jumps_left)
|
||||
self.jumpcounttxt_lbl.grid()
|
||||
else:
|
||||
self.jumpcounttxt_lbl.grid_remove()
|
||||
|
||||
self.waypoint_prev_btn.grid()
|
||||
self.waypoint_btn.grid()
|
||||
self.waypoint_next_btn.grid()
|
||||
|
||||
if self.offset == 0:
|
||||
self.waypoint_prev_btn.config(state=tk.DISABLED)
|
||||
else:
|
||||
self.waypoint_prev_btn.config(state=tk.NORMAL)
|
||||
|
||||
if self.offset == self.route.__len__()-1:
|
||||
self.waypoint_next_btn.config(state=tk.DISABLED)
|
||||
else:
|
||||
self.waypoint_next_btn.config(state=tk.NORMAL)
|
||||
|
||||
self.clear_route_btn.grid()
|
||||
|
||||
def update_gui(self):
|
||||
self.show_route_gui(True)
|
||||
|
||||
def show_error(self, error):
|
||||
self.error_txt.set(error)
|
||||
self.error_lbl.grid()
|
||||
|
||||
def hide_error(self):
|
||||
self.error_lbl.grid_remove()
|
||||
|
||||
def enable_plot_gui(self, enable):
|
||||
if enable:
|
||||
self.source_ac.config(state=tk.NORMAL)
|
||||
self.source_ac.update_idletasks()
|
||||
self.dest_ac.config(state=tk.NORMAL)
|
||||
self.dest_ac.update_idletasks()
|
||||
self.efficiency_slider.config(state=tk.NORMAL)
|
||||
self.efficiency_slider.update_idletasks()
|
||||
self.range_entry.config(state=tk.NORMAL)
|
||||
self.range_entry.update_idletasks()
|
||||
self.plot_route_btn.config(state=tk.NORMAL, text="Calculate")
|
||||
self.plot_route_btn.update_idletasks()
|
||||
self.cancel_plot.config(state=tk.NORMAL)
|
||||
self.cancel_plot.update_idletasks()
|
||||
else:
|
||||
self.source_ac.config(state=tk.DISABLED)
|
||||
self.source_ac.update_idletasks()
|
||||
self.dest_ac.config(state=tk.DISABLED)
|
||||
self.dest_ac.update_idletasks()
|
||||
self.efficiency_slider.config(state=tk.DISABLED)
|
||||
self.efficiency_slider.update_idletasks()
|
||||
self.range_entry.config(state=tk.DISABLED)
|
||||
self.range_entry.update_idletasks()
|
||||
self.plot_route_btn.config(state=tk.DISABLED, text="Computing...")
|
||||
self.plot_route_btn.update_idletasks()
|
||||
self.cancel_plot.config(state=tk.DISABLED)
|
||||
self.cancel_plot.update_idletasks()
|
||||
|
||||
# -- END GUI part --
|
||||
|
||||
|
||||
def open_last_route(self):
|
||||
try:
|
||||
has_headers = False
|
||||
with open(self.save_route_path, 'r') as csvfile:
|
||||
# Check if the file has a header for compatibility with previous versions
|
||||
dict_route_reader = csv.DictReader(csvfile)
|
||||
if dict_route_reader.fieldnames[0] == self.system_header:
|
||||
has_headers = True
|
||||
|
||||
if has_headers:
|
||||
self.plot_csv(self.save_route_path, clear_previous_route=False)
|
||||
else:
|
||||
with open(self.save_route_path, 'r') as csvfile:
|
||||
route_reader = csv.reader(csvfile)
|
||||
|
||||
for row in route_reader:
|
||||
if row not in (None, "", []):
|
||||
self.route.append(row)
|
||||
|
||||
try:
|
||||
with open(self.offset_file_path, 'r') as offset_fh:
|
||||
self.offset = int(offset_fh.readline())
|
||||
|
||||
except:
|
||||
self.offset = 0
|
||||
|
||||
self.jumps_left = 0
|
||||
for row in self.route[self.offset:]:
|
||||
if row[1] not in [None, "", []]:
|
||||
self.jumps_left += int(row[1])
|
||||
|
||||
self.next_stop = self.route[self.offset][0]
|
||||
self.copy_waypoint()
|
||||
except:
|
||||
print("No previously saved route.")
|
||||
|
||||
def copy_waypoint(self):
|
||||
if sys.platform == "linux" or sys.platform == "linux2":
|
||||
command = subprocess.Popen(["echo", "-n", self.next_stop], stdout=subprocess.PIPE)
|
||||
subprocess.Popen(["xclip", "-selection", "c"], stdin=command.stdout)
|
||||
else:
|
||||
self.parent.clipboard_clear()
|
||||
self.parent.clipboard_append(self.next_stop)
|
||||
self.parent.update()
|
||||
|
||||
def goto_next_waypoint(self):
|
||||
if self.offset < self.route.__len__()-1:
|
||||
self.update_route(1)
|
||||
|
||||
def goto_prev_waypoint(self):
|
||||
if self.offset > 0:
|
||||
self.update_route(-1)
|
||||
|
||||
def update_route(self, direction=1):
|
||||
if direction > 0:
|
||||
if self.route[self.offset][1] not in [None, "", []]:
|
||||
self.jumps_left -= int(self.route[self.offset][1])
|
||||
self.offset += 1
|
||||
else:
|
||||
self.offset -= 1
|
||||
if self.route[self.offset][1] not in [None, "", []]:
|
||||
self.jumps_left += int(self.route[self.offset][1])
|
||||
|
||||
if self.offset >= self.route.__len__():
|
||||
self.next_stop = "End of the road!"
|
||||
self.update_gui()
|
||||
else:
|
||||
self.next_stop = self.route[self.offset][0]
|
||||
self.update_gui()
|
||||
self.copy_waypoint()
|
||||
self.save_offset()
|
||||
|
||||
def goto_changelog_page(self):
|
||||
changelog_url = 'https://github.com/CMDR-Kiel42/EDMC_SpanshRouter/blob/master/CHANGELOG.md#'
|
||||
changelog_url += self.spansh_updater.version.replace('.', '')
|
||||
webbrowser.open(changelog_url)
|
||||
|
||||
def plot_file(self):
|
||||
ftypes = [
|
||||
('All supported files', '*.csv *.txt'),
|
||||
('CSV files', '*.csv'),
|
||||
('Text files', '*.txt'),
|
||||
]
|
||||
filename = filedialog.askopenfilename(filetypes = ftypes)
|
||||
|
||||
if filename.__len__() > 0:
|
||||
try:
|
||||
ftype_supported = False
|
||||
if filename.endswith(".csv"):
|
||||
ftype_supported = True
|
||||
self.plot_csv(filename)
|
||||
|
||||
elif filename.endswith(".txt"):
|
||||
ftype_supported = True
|
||||
self.plot_edts(filename)
|
||||
|
||||
if ftype_supported:
|
||||
self.offset = 0
|
||||
self.next_stop = self.route[0][0]
|
||||
self.copy_waypoint()
|
||||
self.update_gui()
|
||||
self.save_all_route()
|
||||
else:
|
||||
self.show_error("Unsupported file type")
|
||||
except:
|
||||
exc_type, exc_value, exc_traceback = sys.exc_info()
|
||||
lines = traceback.format_exception(exc_type, exc_value, exc_traceback)
|
||||
sys.stderr.write(''.join('!! ' + line for line in lines))
|
||||
self.enable_plot_gui(True)
|
||||
self.show_error("An error occured while reading the file.")
|
||||
|
||||
def plot_csv(self, filename, clear_previous_route=True):
|
||||
with open(filename, 'r') as csvfile:
|
||||
route_reader = csv.DictReader(csvfile)
|
||||
|
||||
if clear_previous_route:
|
||||
self.clear_route(False)
|
||||
for row in route_reader:
|
||||
if row not in (None, "", []):
|
||||
self.route.append([
|
||||
row[self.system_header],
|
||||
row.get(self.jumps_header, "") # Jumps column is optional
|
||||
])
|
||||
if row.get(self.jumps_header) != None:
|
||||
self.jumps_left += int(row[self.jumps_header])
|
||||
|
||||
def plot_route(self):
|
||||
self.hide_error()
|
||||
try:
|
||||
source = self.source_ac.get().strip()
|
||||
dest = self.dest_ac.get().strip()
|
||||
efficiency = self.efficiency_slider.get()
|
||||
|
||||
if ( source and source != self.source_ac.placeholder and
|
||||
dest and dest != self.dest_ac.placeholder ):
|
||||
|
||||
try:
|
||||
range_ly = float(self.range_entry.get())
|
||||
except ValueError:
|
||||
self.show_error("Invalid range")
|
||||
return
|
||||
|
||||
job_url="https://spansh.co.uk/api/route?"
|
||||
|
||||
results = requests.post(job_url, params={
|
||||
"efficiency": efficiency,
|
||||
"range": range_ly,
|
||||
"from": source,
|
||||
"to": dest
|
||||
}, headers={'User-Agent': "EDMC_SpanshRouter 1.0"})
|
||||
|
||||
if results.status_code == 202:
|
||||
self.enable_plot_gui(False)
|
||||
|
||||
tries = 0
|
||||
while(tries < 20):
|
||||
response = json.loads(results.content)
|
||||
job = response["job"]
|
||||
|
||||
results_url = "https://spansh.co.uk/api/results/" + job
|
||||
route_response = requests.get(results_url, timeout=5)
|
||||
if route_response.status_code != 202:
|
||||
break
|
||||
tries += 1
|
||||
sleep(1)
|
||||
|
||||
if route_response:
|
||||
if route_response.status_code == 200:
|
||||
route = json.loads(route_response.content)["result"]["system_jumps"]
|
||||
self.clear_route(show_dialog=False)
|
||||
for waypoint in route:
|
||||
self.route.append([waypoint["system"], str(waypoint["jumps"])])
|
||||
self.jumps_left += waypoint["jumps"]
|
||||
self.enable_plot_gui(True)
|
||||
self.show_plot_gui(False)
|
||||
self.offset = 1 if self.route[0][0] == monitor.system else 0
|
||||
self.next_stop = self.route[self.offset][0]
|
||||
self.copy_waypoint()
|
||||
self.update_gui()
|
||||
self.save_all_route()
|
||||
else:
|
||||
sys.stderr.write("Failed to query plotted route from Spansh: code " + str(route_response.status_code) + route_response.text + '\n')
|
||||
self.enable_plot_gui(True)
|
||||
failure = json.loads(results.content)
|
||||
|
||||
if route_response.status_code == 400 and "error" in failure:
|
||||
self.show_error(failure["error"])
|
||||
if "starting system" in failure["error"]:
|
||||
self.source_ac["fg"] = "red"
|
||||
if "finishing system" in failure["error"]:
|
||||
self.dest_ac["fg"] = "red"
|
||||
else:
|
||||
self.show_error(self.plot_error)
|
||||
else:
|
||||
sys.stderr.write("Query to Spansh timed out")
|
||||
self.enable_plot_gui(True)
|
||||
self.show_error("The query to Spansh was too long and timed out, please try again.")
|
||||
else:
|
||||
sys.stderr.write("Failed to query plotted route from Spansh: code " + str(results.status_code) + results.text + '\n')
|
||||
self.enable_plot_gui(True)
|
||||
failure = json.loads(results.content)
|
||||
|
||||
if results.status_code == 400 and "error" in failure:
|
||||
self.show_error(failure["error"])
|
||||
if "starting system" in failure["error"]:
|
||||
self.source_ac["fg"] = "red"
|
||||
if "finishing system" in failure["error"]:
|
||||
self.dest_ac["fg"] = "red"
|
||||
else:
|
||||
self.show_error(self.plot_error)
|
||||
|
||||
except:
|
||||
exc_type, exc_value, exc_traceback = sys.exc_info()
|
||||
lines = traceback.format_exception(exc_type, exc_value, exc_traceback)
|
||||
sys.stderr.write(''.join('!! ' + line for line in lines))
|
||||
self.enable_plot_gui(True)
|
||||
self.show_error(self.plot_error)
|
||||
|
||||
def plot_edts(self, filename):
|
||||
try:
|
||||
with open(filename, 'r') as txtfile:
|
||||
route_txt = txtfile.readlines()
|
||||
self.clear_route(False)
|
||||
for row in route_txt:
|
||||
if row not in (None, "", []):
|
||||
if row.lstrip().startswith('==='):
|
||||
jumps = int(re.findall("\d+ jump", row)[0].rstrip(' jumps'))
|
||||
self.jumps_left += jumps
|
||||
|
||||
system = row[row.find('>') + 1:]
|
||||
if ',' in system:
|
||||
systems = system.split(',')
|
||||
for system in systems:
|
||||
self.route.append([system.strip(), jumps])
|
||||
jumps = 1
|
||||
self.jumps_left += jumps
|
||||
else:
|
||||
self.route.append([system.strip(), jumps])
|
||||
except:
|
||||
exc_type, exc_value, exc_traceback = sys.exc_info()
|
||||
lines = traceback.format_exception(exc_type, exc_value, exc_traceback)
|
||||
sys.stderr.write(''.join('!! ' + line for line in lines))
|
||||
self.enable_plot_gui(True)
|
||||
self.show_error("An error occured while reading the file.")
|
||||
|
||||
def clear_route(self, show_dialog=True):
|
||||
clear = confirmDialog.askyesno("SpanshRouter","Are you sure you want to clear the current route?") if show_dialog else True
|
||||
|
||||
if clear:
|
||||
self.offset = 0
|
||||
self.route = []
|
||||
self.next_waypoint = ""
|
||||
self.jumps_left = 0
|
||||
try:
|
||||
os.remove(self.save_route_path)
|
||||
except:
|
||||
print("No route to delete")
|
||||
try:
|
||||
os.remove(self.offset_file_path)
|
||||
except:
|
||||
print("No offset file to delete")
|
||||
|
||||
self.update_gui()
|
||||
|
||||
def save_all_route(self):
|
||||
self.save_route()
|
||||
self.save_offset()
|
||||
|
||||
def save_route(self):
|
||||
if self.route.__len__() != 0:
|
||||
with open(self.save_route_path, 'w') as csvfile:
|
||||
fieldnames = [self.system_header, self.jumps_header]
|
||||
writer = csv.writer(csvfile)
|
||||
writer.writerow(fieldnames)
|
||||
writer.writerows(self.route)
|
||||
else:
|
||||
try:
|
||||
os.remove(self.save_route_path)
|
||||
except:
|
||||
print("No route to delete")
|
||||
|
||||
def save_offset(self):
|
||||
if self.route.__len__() != 0:
|
||||
with open(self.offset_file_path, 'w') as offset_fh:
|
||||
offset_fh.write(str(self.offset))
|
||||
else:
|
||||
try:
|
||||
os.remove(self.offset_file_path)
|
||||
except:
|
||||
print("No offset to delete")
|
||||
|
||||
def check_range(self, name, index, mode):
|
||||
value = self.range_entry.var.get()
|
||||
if value.__len__() > 0 and value != self.range_entry.placeholder:
|
||||
try:
|
||||
float(value)
|
||||
self.range_entry.set_error_style(False)
|
||||
self.hide_error()
|
||||
except ValueError:
|
||||
self.show_error("Invalid range")
|
||||
self.range_entry.set_error_style()
|
||||
|
||||
def cleanup_old_version(self):
|
||||
try:
|
||||
if (os.path.exists(os.path.join(self.plugin_dir, "AutoCompleter.py"))
|
||||
and os.path.exists(os.path.join(self.plugin_dir, "SpanshRouter"))):
|
||||
files_list = os.listdir(self.plugin_dir)
|
||||
|
||||
for filename in files_list:
|
||||
if (filename != "load.py"
|
||||
and (filename.endswith(".py") or filename.endswith(".pyc") or filename.endswith(".pyo"))):
|
||||
os.remove(os.path.join(self.plugin_dir, filename))
|
||||
except:
|
||||
exc_type, exc_value, exc_traceback = sys.exc_info()
|
||||
lines = traceback.format_exception(exc_type, exc_value, exc_traceback)
|
||||
sys.stderr.write(''.join('!! ' + line for line in lines))
|
||||
|
||||
def check_for_update(self):
|
||||
self.cleanup_old_version()
|
||||
version_url = "https://raw.githubusercontent.com/CMDR-Kiel42/EDMC_SpanshRouter/master/version.json"
|
||||
try:
|
||||
response = requests.get(version_url, timeout=2)
|
||||
|
||||
if response.status_code == 200:
|
||||
if self.plugin_version != response.content:
|
||||
self.update_available = True
|
||||
self.spansh_updater = SpanshUpdater(response.content, self.plugin_dir)
|
||||
|
||||
else:
|
||||
sys.stderr.write("Could not query latest SpanshRouter version: " + str(response.status_code) + response.text)
|
||||
except:
|
||||
exc_type, exc_value, exc_traceback = sys.exc_info()
|
||||
lines = traceback.format_exception(exc_type, exc_value, exc_traceback)
|
||||
sys.stderr.write(''.join('!! ' + line for line in lines))
|
||||
|
||||
def install_update(self):
|
||||
self.spansh_updater.install()
|
@ -18,7 +18,7 @@ try:
|
||||
from Tkinter import *
|
||||
import tkFileDialog as filedialog
|
||||
import tkMessageBox as confirmDialog
|
||||
import ttk
|
||||
import ttk
|
||||
except ModuleNotFoundError:
|
||||
# Python 3
|
||||
import tkinter as tk
|
||||
@ -31,7 +31,7 @@ class SpanshRouter():
|
||||
version_file = os.path.join(plugin_dir, "version.json")
|
||||
with open(version_file, 'r') as version_fd:
|
||||
self.plugin_version = version_fd.read()
|
||||
|
||||
|
||||
self.update_available = False
|
||||
self.next_stop = "No route planned"
|
||||
self.route = []
|
||||
@ -48,7 +48,7 @@ class SpanshRouter():
|
||||
self.system_header = "System Name"
|
||||
self.jumps_header = "Jumps"
|
||||
|
||||
# -- GUI part --
|
||||
# -- GUI part --
|
||||
def init_gui(self, parent):
|
||||
self.parent = parent
|
||||
parentwidth = parent.winfo_width()
|
||||
@ -71,7 +71,7 @@ class SpanshRouter():
|
||||
self.plot_gui_btn = tk.Button(self.frame, text="Plot route", command=self.show_plot_gui)
|
||||
self.plot_route_btn = tk.Button(self.frame, text="Calculate", command=self.plot_route)
|
||||
self.cancel_plot = tk.Button(self.frame, text="Cancel", command=lambda: self.show_plot_gui(False))
|
||||
|
||||
|
||||
self.csv_route_btn = tk.Button(self.frame, text="Import file", command=self.plot_file)
|
||||
self.clear_route_btn = tk.Button(self.frame, text="Clear route", command=self.clear_route)
|
||||
|
||||
@ -126,7 +126,7 @@ class SpanshRouter():
|
||||
confirmDialog.showinfo("SpanshRouter", "The update will be installed as soon as you quit EDMC.")
|
||||
else:
|
||||
self.update_available = False
|
||||
|
||||
|
||||
self.update_gui()
|
||||
|
||||
return self.frame
|
||||
@ -249,7 +249,7 @@ class SpanshRouter():
|
||||
self.cancel_plot.config(state=tk.DISABLED)
|
||||
self.cancel_plot.update_idletasks()
|
||||
|
||||
# -- END GUI part --
|
||||
# -- END GUI part --
|
||||
|
||||
|
||||
def open_last_route(self):
|
||||
@ -328,7 +328,7 @@ class SpanshRouter():
|
||||
changelog_url = 'https://github.com/CMDR-Kiel42/EDMC_SpanshRouter/blob/master/CHANGELOG.md#'
|
||||
changelog_url += self.spansh_updater.version.replace('.', '')
|
||||
webbrowser.open(changelog_url)
|
||||
|
||||
|
||||
def plot_file(self):
|
||||
ftypes = [
|
||||
('All supported files', '*.csv *.txt'),
|
||||
@ -343,7 +343,7 @@ class SpanshRouter():
|
||||
if filename.endswith(".csv"):
|
||||
ftype_supported = True
|
||||
self.plot_csv(filename)
|
||||
|
||||
|
||||
elif filename.endswith(".txt"):
|
||||
ftype_supported = True
|
||||
self.plot_edts(filename)
|
||||
@ -372,7 +372,7 @@ class SpanshRouter():
|
||||
for row in route_reader:
|
||||
if row not in (None, "", []):
|
||||
self.route.append([
|
||||
row[self.system_header],
|
||||
row[self.system_header],
|
||||
row.get(self.jumps_header, "") # Jumps column is optional
|
||||
])
|
||||
if row.get(self.jumps_header) != None:
|
||||
@ -405,7 +405,7 @@ class SpanshRouter():
|
||||
|
||||
if results.status_code == 202:
|
||||
self.enable_plot_gui(False)
|
||||
|
||||
|
||||
tries = 0
|
||||
while(tries < 20):
|
||||
response = json.loads(results.content)
|
||||
@ -428,7 +428,7 @@ class SpanshRouter():
|
||||
self.enable_plot_gui(True)
|
||||
self.show_plot_gui(False)
|
||||
self.offset = 1 if self.route[0][0] == monitor.system else 0
|
||||
self.next_stop = self.route[self.offset][0]
|
||||
self.next_stop = self.route[self.offset][0]
|
||||
self.copy_waypoint()
|
||||
self.update_gui()
|
||||
self.save_all_route()
|
||||
@ -438,7 +438,7 @@ class SpanshRouter():
|
||||
failure = json.loads(results.content)
|
||||
|
||||
if route_response.status_code == 400 and "error" in failure:
|
||||
self.show_error(failure["error"])
|
||||
self.show_error(failure["error"])
|
||||
if "starting system" in failure["error"]:
|
||||
self.source_ac["fg"] = "red"
|
||||
if "finishing system" in failure["error"]:
|
||||
@ -455,14 +455,14 @@ class SpanshRouter():
|
||||
failure = json.loads(results.content)
|
||||
|
||||
if results.status_code == 400 and "error" in failure:
|
||||
self.show_error(failure["error"])
|
||||
self.show_error(failure["error"])
|
||||
if "starting system" in failure["error"]:
|
||||
self.source_ac["fg"] = "red"
|
||||
if "finishing system" in failure["error"]:
|
||||
self.dest_ac["fg"] = "red"
|
||||
else:
|
||||
self.show_error(self.plot_error)
|
||||
|
||||
|
||||
except:
|
||||
exc_type, exc_value, exc_traceback = sys.exc_info()
|
||||
lines = traceback.format_exception(exc_type, exc_value, exc_traceback)
|
||||
@ -532,7 +532,7 @@ class SpanshRouter():
|
||||
os.remove(self.save_route_path)
|
||||
except:
|
||||
print("No route to delete")
|
||||
|
||||
|
||||
def save_offset(self):
|
||||
if self.route.__len__() != 0:
|
||||
with open(self.offset_file_path, 'w') as offset_fh:
|
||||
@ -561,7 +561,7 @@ class SpanshRouter():
|
||||
files_list = os.listdir(self.plugin_dir)
|
||||
|
||||
for filename in files_list:
|
||||
if (filename != "load.py"
|
||||
if (filename != "load.py"
|
||||
and (filename.endswith(".py") or filename.endswith(".pyc") or filename.endswith(".pyo"))):
|
||||
os.remove(os.path.join(self.plugin_dir, filename))
|
||||
except:
|
||||
@ -574,12 +574,12 @@ class SpanshRouter():
|
||||
version_url = "https://raw.githubusercontent.com/CMDR-Kiel42/EDMC_SpanshRouter/master/version.json"
|
||||
try:
|
||||
response = requests.get(version_url, timeout=2)
|
||||
|
||||
|
||||
if response.status_code == 200:
|
||||
if self.plugin_version != response.content:
|
||||
self.update_available = True
|
||||
self.spansh_updater = SpanshUpdater(response.content, self.plugin_dir)
|
||||
|
||||
|
||||
else:
|
||||
sys.stderr.write("Could not query latest SpanshRouter version: " + str(response.status_code) + response.text)
|
||||
except:
|
||||
|
12
load.py
12
load.py
@ -1,4 +1,9 @@
|
||||
from SpanshRouter import SpanshRouter
|
||||
import sys
|
||||
is_py2 = sys.version[0] == '2'
|
||||
if is_py2:
|
||||
from SpanshRouter import SpanshRouter
|
||||
else:
|
||||
import SpanshRouter as SpanshRouter
|
||||
|
||||
global spansh_router
|
||||
spansh_router = None
|
||||
@ -9,10 +14,9 @@ def plugin_start3(plugin_dir):
|
||||
|
||||
def plugin_start(plugin_dir):
|
||||
# Check for newer versions
|
||||
global spansh_router
|
||||
#spansh_router = SpanshRouter(plugin_dir)
|
||||
spansh_router = SpanshRouter(plugin_dir)
|
||||
#spansh_router.check_for_update()
|
||||
spansh_router.open_last_route()
|
||||
#spansh_router.open_last_route()
|
||||
return 'spansh_router'
|
||||
|
||||
def plugin_stop():
|
||||
|
66
updater.py
Normal file
66
updater.py
Normal file
@ -0,0 +1,66 @@
|
||||
import os
|
||||
import requests
|
||||
import zipfile
|
||||
import sys
|
||||
import traceback
|
||||
import json
|
||||
|
||||
class SpanshUpdater():
|
||||
def __init__(self, version, plugin_dir):
|
||||
self.version = version
|
||||
self.zip_name = "EDMC_SpanshRouter_" + version.replace('.', '') + ".zip"
|
||||
self.plugin_dir = plugin_dir
|
||||
self.zip_path = os.path.join(self.plugin_dir, self.zip_name)
|
||||
self.zip_downloaded = False
|
||||
self.changelogs = self.get_changelog()
|
||||
|
||||
def download_zip(self):
|
||||
url = 'https://github.com/CMDR-Kiel42/EDMC_SpanshRouter/releases/download/v' + self.version + '/' + self.zip_name
|
||||
|
||||
try:
|
||||
r = requests.get(url)
|
||||
if r.status_code == 200:
|
||||
with open(self.zip_path, 'wb') as f:
|
||||
print("Downloading SpanshRouter to " + self.zip_path)
|
||||
f.write(os.path.join(r.content))
|
||||
self.zip_downloaded = True
|
||||
else:
|
||||
sys.stderr.write("Failed to fetch SpanchRouter update. Status code: " + str(r.status_code))
|
||||
self.zip_downloaded = False
|
||||
except:
|
||||
exc_type, exc_value, exc_traceback = sys.exc_info()
|
||||
lines = traceback.format_exception(exc_type, exc_value, exc_traceback)
|
||||
sys.stderr.write(''.join('!! ' + line for line in lines))
|
||||
self.zip_downloaded = False
|
||||
finally:
|
||||
return self.zip_downloaded
|
||||
|
||||
def install(self):
|
||||
if self.download_zip():
|
||||
try:
|
||||
with zipfile.ZipFile(self.zip_path, 'r') as zip_ref:
|
||||
zip_ref.extractall(self.plugin_dir)
|
||||
|
||||
os.remove(self.zip_path)
|
||||
except:
|
||||
exc_type, exc_value, exc_traceback = sys.exc_info()
|
||||
lines = traceback.format_exception(exc_type, exc_value, exc_traceback)
|
||||
sys.stderr.write(''.join('!! ' + line for line in lines))
|
||||
else:
|
||||
sys.stderr.write("Error when downloading the latest SpanshRouter update")
|
||||
|
||||
def get_changelog(self):
|
||||
url = "https://api.github.com/repos/CMDR-Kiel42/EDMC_SpanshRouter/releases/latest"
|
||||
try:
|
||||
r = requests.get(url, timeout=2)
|
||||
|
||||
if r.status_code == 200:
|
||||
# Get the changelog and replace all breaklines with simple ones
|
||||
changelogs = json.loads(r.content)["body"]
|
||||
changelogs = "\n".join(changelogs.splitlines())
|
||||
return changelogs
|
||||
|
||||
except:
|
||||
exc_type, exc_value, exc_traceback = sys.exc_info()
|
||||
lines = traceback.format_exception(exc_type, exc_value, exc_traceback)
|
||||
sys.stderr.write(''.join('!! ' + line for line in lines))
|
Loading…
x
Reference in New Issue
Block a user