__main__
This commit is contained in:
parent
b2f7a7161b
commit
c152e511a0
455
__main__.py
Normal file
455
__main__.py
Normal file
@ -0,0 +1,455 @@
|
|||||||
|
import tkinter as tk
|
||||||
|
from tkinter import ttk
|
||||||
|
from tkinter import messagebox, font
|
||||||
|
from ttkthemes import ThemedTk
|
||||||
|
from tkinter.scrolledtext import ScrolledText
|
||||||
|
import json
|
||||||
|
import webbrowser
|
||||||
|
from subprocess import Popen, PIPE
|
||||||
|
from pathlib import Path
|
||||||
|
import threading
|
||||||
|
from sys import platform
|
||||||
|
import requests
|
||||||
|
from hashlib import sha256
|
||||||
|
from os import listdir
|
||||||
|
from os.path import isfile, join, exists
|
||||||
|
import shutil
|
||||||
|
|
||||||
|
logarr = []
|
||||||
|
with open('lang.json') as f: lang=json.load(f)
|
||||||
|
|
||||||
|
class menus:
|
||||||
|
def clientmenu(file, mainframe):
|
||||||
|
for child in mainframe.winfo_children(): child.destroy()
|
||||||
|
checkclient = str(helpers.check4client(helpers.getclientpath(file)))
|
||||||
|
clientdetect = ttk.Label(mainframe, text=f"Was Bootstrapper found: {checkclient}", anchor=tk.W)
|
||||||
|
clientdetect.grid(row=0, sticky=tk.W)
|
||||||
|
#not threading this prob stalls the gui, but it's not like the server, where I actually need it to run in the background; in otherwords, I do not care :)
|
||||||
|
dlldownload = ttk.Button(mainframe, text="Download Latest Bootstrapper", command=lambda: helpers.downloadlatestdll(helpers.getclientpath(file)))
|
||||||
|
dlldownload.grid(row=1, sticky=tk.W)
|
||||||
|
|
||||||
|
#menu for pluto scripts; running them is not currently implemented
|
||||||
|
def plutomenu(file, mainframe):
|
||||||
|
for child in mainframe.winfo_children(): child.destroy()
|
||||||
|
openwfpath = helpers.getclientpath(file) + "/OpenWF/scripts/"
|
||||||
|
def openfolder(folder):
|
||||||
|
Popen(['xdg-open', folder])
|
||||||
|
|
||||||
|
onlyfiles = [f for f in listdir(openwfpath) if isfile(join(openwfpath, f))]
|
||||||
|
i = 0
|
||||||
|
for file in onlyfiles:
|
||||||
|
filelabel = ttk.Label(mainframe, text=file, anchor=tk.W)
|
||||||
|
filelabel.grid(row = i, column = 0, sticky = tk.W, pady = 2)
|
||||||
|
plutorun = ttk.Button(mainframe, text="Running not implemented yet", command=lambda: runpluto(file))
|
||||||
|
plutorun.grid(row = i, column = 1, sticky = tk.W, pady = 2, padx=10)
|
||||||
|
i += 1
|
||||||
|
|
||||||
|
# Input would be a json file
|
||||||
|
def settingsmenu(file, mainframe, vcmd):
|
||||||
|
|
||||||
|
for child in mainframe.winfo_children(): child.destroy()
|
||||||
|
if Path(file).is_file():
|
||||||
|
with open(file) as f:
|
||||||
|
settings = json.load(f)
|
||||||
|
i = 0
|
||||||
|
frameunder = ttk.Frame(mainframe)
|
||||||
|
tempsettings = {}
|
||||||
|
print(settings)
|
||||||
|
for key in settings.keys():
|
||||||
|
if key in lang.keys():
|
||||||
|
item = ttk.Label(frameunder, text=(lang[key] + " : "))
|
||||||
|
else:
|
||||||
|
item = ttk.Label(frameunder, text=(key + " : "))
|
||||||
|
item.grid(row = i, column = 0, sticky = tk.W, pady = 2)
|
||||||
|
print (type(settings[key]))
|
||||||
|
if type(settings[key]) is str:
|
||||||
|
value = ttk.Entry(frameunder, width=50)
|
||||||
|
value.insert(0,settings[key])
|
||||||
|
|
||||||
|
elif type(settings[key]) not in [str, bool, int, dict]:
|
||||||
|
value = ttk.Label(frameunder, text="N/A")
|
||||||
|
elif type(settings[key]) is bool:
|
||||||
|
boeol = tk.StringVar()
|
||||||
|
value = ttk.OptionMenu(frameunder, boeol, settings[key], True, False)
|
||||||
|
|
||||||
|
elif type(settings[key]) is int:
|
||||||
|
value = ttk.Entry(frameunder, width=50, validate='key', validatecommand=(vcmd, '%P'))
|
||||||
|
value.insert(0,settings[key])
|
||||||
|
#stupid ass nested dicts eat my whole balls
|
||||||
|
elif type(settings[key]) is dict:
|
||||||
|
value = {}
|
||||||
|
for k in settings[key].keys():
|
||||||
|
value[k] ={}
|
||||||
|
if type(settings[key][k]) is str:
|
||||||
|
value[k]["value"] = ttk.Entry(frameunder, width=50)
|
||||||
|
value[k]["value"].insert(0,settings[key][k])
|
||||||
|
elif type(settings[key][k]) not in [str, bool, int]:
|
||||||
|
value[k]["value"] = ttk.Label(frameunder, text="N/A")
|
||||||
|
elif type(settings[key][k]) is bool:
|
||||||
|
boeol = tk.BooleanVar()
|
||||||
|
value[k]["value"] = ttk.OptionMenu(frameunder, boeol, settings[key][k], True, False)
|
||||||
|
boeol.set(settings[key][k])
|
||||||
|
value[k]["valueop"] = boeol
|
||||||
|
elif type(settings[key][k]) is int:
|
||||||
|
value[k]["value"] = ttk.Entry(frameunder, width=50, validate='key', validatecommand=(vcmd, '%P'))
|
||||||
|
value[k]["value"].insert(0,settings[key][k])
|
||||||
|
value[k]["type"] = type(settings[key][k])
|
||||||
|
|
||||||
|
|
||||||
|
if type(value) is not dict:
|
||||||
|
value.grid(row = i, column = 1, sticky = tk.W, pady = 2)
|
||||||
|
i += 1
|
||||||
|
else:
|
||||||
|
i+=1
|
||||||
|
sp1=ttk.Separator(mainframe,orient='horizontal')
|
||||||
|
sp1.grid(row=i,column=1,sticky='ew')
|
||||||
|
i+=1
|
||||||
|
for k in value.keys():
|
||||||
|
print(k)
|
||||||
|
dictlabel = ttk.Label(frameunder, text=(k + " : "))
|
||||||
|
dictlabel.grid(row = i, column = 0, sticky = tk.E, pady = 2)
|
||||||
|
value[k]["value"].grid(row = i, column = 1, sticky = tk.W, pady = 2)
|
||||||
|
i+=1
|
||||||
|
ttk.Separator(mainframe, orient=tk.HORIZONTAL).grid(row=i)
|
||||||
|
i+=1
|
||||||
|
if type(settings[key]) is bool:
|
||||||
|
tempsettings[key] = {
|
||||||
|
"value" : boeol,
|
||||||
|
"type" : type(settings[key])
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
tempsettings[key] = {
|
||||||
|
"value" : value,
|
||||||
|
"type" : type(settings[key])
|
||||||
|
}
|
||||||
|
|
||||||
|
save = ttk.Button(frameunder, command=lambda: helpers.savefile(file, tempsettings), text="SAVE")
|
||||||
|
save.grid(row=i, column=2, sticky=tk.E, pady=2)
|
||||||
|
frameunder.grid()
|
||||||
|
|
||||||
|
|
||||||
|
def servermenu(mainframe, configfile):
|
||||||
|
for child in mainframe.winfo_children(): child.destroy() #oneline to destroy everything in the main frame
|
||||||
|
side1 = ttk.Frame(mainframe)
|
||||||
|
side2 = ttk.Frame(mainframe)
|
||||||
|
# Side one of the 'server' menu
|
||||||
|
logarea = ScrolledText(side2,
|
||||||
|
wrap = tk.WORD,
|
||||||
|
state="disabled")
|
||||||
|
|
||||||
|
startb = ttk.Button(side1, text="Start Server", command=lambda: [helpers.bgthread(helpers.serverbackground, [helpers.getsnpath(configfile), logarea])])
|
||||||
|
startb.grid(row = 0, column = 0, sticky = tk.W, pady = 2)
|
||||||
|
# Side two of the 'server' menu
|
||||||
|
|
||||||
|
logarea.grid(row = 0, column = 0, sticky = tk.E, pady = 2)
|
||||||
|
|
||||||
|
side1.grid(row = 0, column = 0, sticky = tk.N, pady = 2)
|
||||||
|
side2.grid(row = 0, column = 1, sticky = tk.N, pady = 2)
|
||||||
|
|
||||||
|
class helpers:
|
||||||
|
def downloadlatestdll(filepath):
|
||||||
|
x = requests.get('https://openwf.io/supplementals/client%20drop-in/meta')
|
||||||
|
meta = json.loads(x.text)
|
||||||
|
url = f"https://openwf.io/supplementals/client%20drop-in/{meta['version']}/dwmapi.dll"
|
||||||
|
|
||||||
|
content = requests.get(url, stream=True).content
|
||||||
|
hashofdll = sha256()
|
||||||
|
hashofdll.update(content)
|
||||||
|
|
||||||
|
if hashofdll.hexdigest() == meta['sha256']:
|
||||||
|
with open(filepath + "dwmapi.dll", "wb") as out_file:
|
||||||
|
out_file.write(content)
|
||||||
|
messagebox.showinfo(title="Bootstrapper Downloaded", message="Bootstrapper Downloaded!")
|
||||||
|
else:
|
||||||
|
messagebox.showerror(title="Unknown Error.", message="SpaceninGUI could not verify the hash of the Bootstrapper. Sorry :(")
|
||||||
|
|
||||||
|
def check4client(clientpath):
|
||||||
|
onlyfiles = [f for f in listdir(clientpath) if isfile(join(clientpath, f))]
|
||||||
|
if "dwmapi.dll" in onlyfiles:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Not implemented yet lol
|
||||||
|
def runpluto(name):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def is_number(data):
|
||||||
|
"""Validate the contents of an entry widget as a int."""
|
||||||
|
if data == '':
|
||||||
|
return True
|
||||||
|
try:
|
||||||
|
rv = int(data)
|
||||||
|
except ValueError:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
def savefile(file, save):
|
||||||
|
if Path(file).is_file:
|
||||||
|
with open(file) as f:
|
||||||
|
data = json.load(f)
|
||||||
|
|
||||||
|
for key in save.keys():
|
||||||
|
if save[key]["type"] is bool:
|
||||||
|
if save[key]['value'].get() == '1':
|
||||||
|
data[key] = True
|
||||||
|
else:
|
||||||
|
data[key] = False
|
||||||
|
print(save[key]['value'].get())
|
||||||
|
elif save[key]["type"] is str:
|
||||||
|
data[key] = str(save[key]["value"].get())
|
||||||
|
elif save[key]["type"] is int:
|
||||||
|
data[key] = int(save[key]["value"].get())
|
||||||
|
elif save[key]["type"] is dict:
|
||||||
|
for k in save[key]['value'].keys():
|
||||||
|
if save[key]['value'][k]["type"] is bool:
|
||||||
|
data[key][k] = bool(save[key]['value'][k]["valueop"].get())
|
||||||
|
elif save[key]['value'][k]["type"] is str:
|
||||||
|
data[key][k] = str(save[key]['value'][k]["value"].get())
|
||||||
|
elif save[key]['value'][k]["type"] is int:
|
||||||
|
data[key][k] = int(save[key]['value'][k]["value"].get())
|
||||||
|
|
||||||
|
with open(file, "w") as f:
|
||||||
|
json.dump(data, f, indent=2)
|
||||||
|
|
||||||
|
def getclientpath(file):
|
||||||
|
if Path(file).is_file():
|
||||||
|
with open(file) as f:
|
||||||
|
d = json.load(f)
|
||||||
|
return d["wfpath"]
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Grabs the serverpath, returns false if non-existant
|
||||||
|
def getsnpath(file):
|
||||||
|
if Path(file).is_file():
|
||||||
|
with open(file) as f:
|
||||||
|
d = json.load(f)
|
||||||
|
return d["spaceninjapath"]
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def getlogmax():
|
||||||
|
file = 'sngconfig.json'
|
||||||
|
if Path(file).is_file():
|
||||||
|
with open(file) as f:
|
||||||
|
d = json.load(f)
|
||||||
|
return int(d["maxlogsize"])
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def bgthread(func, args):
|
||||||
|
th = threading.Thread(target=func, args=args)
|
||||||
|
th.daemon = True
|
||||||
|
th.start()
|
||||||
|
|
||||||
|
def serverbackground(cd, logarea): # To my knowledge, running the server in the main thread would stall the gui, fuck that lol
|
||||||
|
logmax = helpers.getlogmax()
|
||||||
|
|
||||||
|
def mongo():
|
||||||
|
sysctl = Popen(['systemctl', 'start', 'mongodb'])
|
||||||
|
sysctl.wait()
|
||||||
|
|
||||||
|
|
||||||
|
def execute(cd):
|
||||||
|
popen = Popen(['npm', 'run', 'dev'], stdin=PIPE, stdout=PIPE, universal_newlines=True, cwd=cd)
|
||||||
|
for stdout_line in iter(popen.stdout.readline, ""):
|
||||||
|
yield stdout_line
|
||||||
|
popen.stdout.close()
|
||||||
|
return_code = popen.wait()
|
||||||
|
if return_code:
|
||||||
|
raise subprocess.CalledProcessError(return_code)
|
||||||
|
|
||||||
|
if platform == "linux":
|
||||||
|
print("Running on linux requires mongodb to be started!")
|
||||||
|
mongo()
|
||||||
|
|
||||||
|
for path in execute(cd):
|
||||||
|
if len(logarr) < logmax:
|
||||||
|
logarr.append(path)
|
||||||
|
else:
|
||||||
|
logarr.pop(0)
|
||||||
|
logarr.append(path)
|
||||||
|
if logarea:
|
||||||
|
logarea.configure(state="normal")
|
||||||
|
logarea.delete(1.0, "end")
|
||||||
|
for element in logarr:
|
||||||
|
logarea.insert(tk.INSERT, element)
|
||||||
|
logarea.configure(state="disabled")
|
||||||
|
|
||||||
|
def check4sn(configfile):
|
||||||
|
file = helpers.getsnpath(configfile) + "package.json"
|
||||||
|
if Path(file).is_file():
|
||||||
|
with open(file) as f:
|
||||||
|
d = json.load(f)
|
||||||
|
if (d["name"] == "wf-emulator"):
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def on_closing(root):
|
||||||
|
if messagebox.askokcancel("Quit", "Do you want to quit?"):
|
||||||
|
root.destroy()
|
||||||
|
|
||||||
|
class main:
|
||||||
|
def __init__(self, configfile):
|
||||||
|
|
||||||
|
root = ThemedTk(theme='black', themebg=True)
|
||||||
|
root.title('SpaceNinGui Version 1.0')
|
||||||
|
root.minsize(400, 300)
|
||||||
|
serverlogs = tk.StringVar()
|
||||||
|
wfemucheck = str(helpers.check4sn(configfile))
|
||||||
|
menubar = tk.Menu(root)
|
||||||
|
vcmd = root.register(helpers.is_number)
|
||||||
|
filemenu = tk.Menu(menubar, tearoff=0)
|
||||||
|
filemenu.add_command(label="Options", command=lambda: menus.settingsmenu(file = configfile, mainframe=mainframe, vcmd=vcmd))
|
||||||
|
filemenu.add_separator()
|
||||||
|
filemenu.add_command(label="Exit", command=lambda: helpers.on_closing(root))
|
||||||
|
menubar.add_cascade(label="SpaceNinGUI", menu=filemenu)
|
||||||
|
menubar.add_separator()
|
||||||
|
|
||||||
|
menubar.add_command(label="\u22EE", activebackground=menubar.cget("background"))
|
||||||
|
|
||||||
|
menubar.add_command(label="Server", command=lambda: menus.servermenu(mainframe, configfile))
|
||||||
|
menubar.add_command(label="Settings", command=lambda: menus.settingsmenu(file=(helpers.getsnpath(configfile) + "config.json"), mainframe=mainframe, vcmd=vcmd))
|
||||||
|
mainframe = ttk.Frame(root)
|
||||||
|
menubar.add_command(label="\u22EE", activebackground=menubar.cget("background"))
|
||||||
|
menubar.add_command(label="Client", command=lambda: menus.clientmenu(file="sngconfig.json", mainframe=mainframe))
|
||||||
|
menubar.add_command(label="Settings", command=lambda: menus.settingsmenu(file=(helpers.getclientpath(configfile) + "/OpenWF/client_config.json"), mainframe=mainframe, vcmd=vcmd))
|
||||||
|
menubar.add_command(label="Scripts", command=lambda: menus.plutomenu(file="sngconfig.json", mainframe=mainframe))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
checklabel = ttk.Label(mainframe, text=f"Was Spaceninja Found: {wfemucheck}", anchor=tk.W, font=("Arial", 16, "bold"))
|
||||||
|
checklabel.grid(row = 0, column = 0, sticky = tk.W, pady = 2)
|
||||||
|
mainframe.grid(row = 0, column = 0, pady = 2)
|
||||||
|
root.protocol("WM_DELETE_WINDOW", lambda: helpers.on_closing(root))
|
||||||
|
root.config(menu=menubar)
|
||||||
|
root.mainloop()
|
||||||
|
|
||||||
|
class install():
|
||||||
|
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.step = 1
|
||||||
|
|
||||||
|
self.config = {}
|
||||||
|
self.elements = {}
|
||||||
|
|
||||||
|
root = ThemedTk(theme='black', themebg=True)
|
||||||
|
self.root = root
|
||||||
|
self.installstep=tk.StringVar()
|
||||||
|
self.installprog=tk.IntVar()
|
||||||
|
self.installprog.set(0)
|
||||||
|
self.installstep.set("Init")
|
||||||
|
#font options lmao
|
||||||
|
standard = ('Noto Sans', 10)
|
||||||
|
standardbold = ('Noto Sans', 10, "bold")
|
||||||
|
self.standard = standard
|
||||||
|
self.standardbold = standardbold
|
||||||
|
|
||||||
|
root.title('SpaceNinGui Installer')
|
||||||
|
root.minsize(400, 300)
|
||||||
|
leftframe = ttk.Frame(root, borderwidth=10)
|
||||||
|
rightframe = ttk.Frame(root, borderwidth=1)
|
||||||
|
steps=["1: Initial Message", "2: Install Spaceninja Server", "3: Install Warframe Bootstrapper", "4: Final Steps"]
|
||||||
|
ttk.Label(leftframe, text="Steps:").grid(padx=20)
|
||||||
|
self.steplabel=[]
|
||||||
|
for step in steps:
|
||||||
|
label=ttk.Label(leftframe, text=step, anchor=tk.W)
|
||||||
|
self.steplabel.append(label)
|
||||||
|
for label in self.steplabel:
|
||||||
|
label.grid(padx=20, pady=5, sticky=tk.W)
|
||||||
|
|
||||||
|
|
||||||
|
self.steplabel[0].config(font=standardbold)
|
||||||
|
rightinnerframe = ttk.Frame(rightframe)
|
||||||
|
ttk.Label(rightinnerframe, text="Welcome to SpaceNinGui! \nFirst, We have to get some inital settings setup. \nWe will start with the server configuration.").grid()
|
||||||
|
leftframe.grid(row=0, column=0, sticky=tk.W)
|
||||||
|
|
||||||
|
rightinnerframe.grid()
|
||||||
|
rightframe.grid(row=0, column=1, sticky=tk.E)
|
||||||
|
nextbutton = ttk.Button(rightframe, text="Next", command=lambda: self.next(rightinnerframe))
|
||||||
|
nextbutton.grid(row=1, sticky=tk.SE)
|
||||||
|
root.protocol("WM_DELETE_WINDOW", lambda: helpers.on_closing(root))
|
||||||
|
root.mainloop()
|
||||||
|
|
||||||
|
def configsave(self):
|
||||||
|
with open('sngconfig.json', 'w') as f:
|
||||||
|
tot = {}
|
||||||
|
tot["spaceninjapath"] = self.elements['serverpath'].get()
|
||||||
|
tot["wfpath"] = self.elements['clientpath'].get()
|
||||||
|
tot['maxlogsize']=10
|
||||||
|
json.dump(tot, f, indent=2)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def install(self, clientpath, serverpath):
|
||||||
|
#first install server
|
||||||
|
self.installstep.set("Downloading Server Through Git")
|
||||||
|
sysctl = Popen(['git', 'clone', 'https://openwf.io/SpaceNinjaServer.git', serverpath])
|
||||||
|
self.installprog.set(1)
|
||||||
|
sysctl.wait()
|
||||||
|
self.installstep.set("Installing Server Requirements (via npm)")
|
||||||
|
self.installprog.set(25)
|
||||||
|
sysctl = Popen(["npm", '--prefix', f'{serverpath}', 'install'])
|
||||||
|
sysctl.wait()
|
||||||
|
self.installstep.set("Copying Config File")
|
||||||
|
shutil.copy(serverpath + "/config.json.example", serverpath + "/config.json")
|
||||||
|
self.installstep.set("Starting Bootstrapper Download")
|
||||||
|
self.installprog.set(50)
|
||||||
|
print("Server install worked. ")
|
||||||
|
helpers.downloadlatestdll(clientpath)
|
||||||
|
self.installprog.set(99)
|
||||||
|
self.installstep.set("Install Complete!\nPress next then restart to get started!")
|
||||||
|
|
||||||
|
|
||||||
|
def next(self, inner):
|
||||||
|
if self.step == 1:
|
||||||
|
self.step+=1
|
||||||
|
for child in inner.winfo_children(): child.destroy()
|
||||||
|
self.elements["serverpath"] = tk.StringVar()
|
||||||
|
path = ttk.Entry(inner, width=50, textvariable=self.elements["serverpath"])
|
||||||
|
flavortext = ttk.Label(inner, text="Please input a path that you would like to install the Server in!")
|
||||||
|
flavortext.grid(padx=10)
|
||||||
|
path.grid(padx=10)
|
||||||
|
self.steplabel[0].config(font=self.standard)
|
||||||
|
self.steplabel[1].config(font=self.standardbold)
|
||||||
|
elif self.step == 2:
|
||||||
|
self.step+=1
|
||||||
|
self.elements["clientpath"] = tk.StringVar()
|
||||||
|
for child in inner.winfo_children(): child.destroy()
|
||||||
|
path = ttk.Entry(inner, width=50, textvariable=self.elements["clientpath"])
|
||||||
|
flavortext = ttk.Label(inner, text="Please input the path that has Warframe installed\nI highly suggest making a copy to prevent potental bans.", anchor=tk.CENTER)
|
||||||
|
flavortext.grid(padx=10, pady=5)
|
||||||
|
path.grid(padx=10)
|
||||||
|
self.elements["wfpath"] = path
|
||||||
|
self.steplabel[1].config(font=self.standard)
|
||||||
|
self.steplabel[2].config(font=self.standardbold)
|
||||||
|
elif self.step == 3:
|
||||||
|
self.step+= 1
|
||||||
|
print("final step!!!")
|
||||||
|
for child in inner.winfo_children(): child.destroy()
|
||||||
|
flavortext = ttk.Label(inner, text="Thank you! The OpenWF setup should be downloading in the background!", anchor=tk.CENTER)
|
||||||
|
flavortext.grid(padx=10, pady=5)
|
||||||
|
statustext = ttk.Label(inner, textvariable=self.installstep, anchor=tk.CENTER)
|
||||||
|
statustext.grid(padx=10, pady=5)
|
||||||
|
statusbar = ttk.Progressbar(inner, variable=self.installprog)
|
||||||
|
statusbar.grid()
|
||||||
|
helpers.bgthread(self.install, [self.elements["clientpath"].get(), self.elements["serverpath"].get()])
|
||||||
|
elif self.step == 4:
|
||||||
|
if self.installstep.get() == "Install Complete!\nPress next then restart to get started!":
|
||||||
|
self.configsave()
|
||||||
|
self.root.destroy()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
if isfile('sngconfig.json'):
|
||||||
|
main('sngconfig.json')
|
||||||
|
else:
|
||||||
|
install()
|
1
requirements.txt
Normal file
1
requirements.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
|
Loading…
x
Reference in New Issue
Block a user