Atlas-Install/source/gui/install.py
2022-06-08 14:39:43 +02:00

212 lines
6.5 KiB
Python

import shutil
import tkinter
from pathlib import Path
import json
from tkinter import ttk
from tkinter import filedialog
from tkinter import messagebox
import webbrowser
from source.translation import translate as _
from source import event
from source import *
import os
# Main window for the installer
class Window(tkinter.Tk):
def __init__(self):
super().__init__()
self.title(_("INSTALLER_TITLE"))
self.resizable(False, False)
self.iconbitmap("./assets/icon.ico")
# menu bar
self.menu = Menu(self)
self.config(menu=self.menu)
# main frame
self.select_pack = SelectPack(self)
self.select_pack.grid(row=1, column=1, sticky="w")
self.source_game = SourceGame(self)
self.source_game.grid(row=2, column=1, sticky="nsew")
self.destination_game = DestinationGame(self)
self.destination_game.grid(row=3, column=1, sticky="nsew")
self.button_install = ButtonInstall(self)
self.button_install.grid(row=4, column=1, sticky="nsew")
self.progress_bar = ProgressBar(self)
self.progress_bar.grid(row=5, column=1, sticky="nsew")
def run(self) -> None:
"""
Run the installer
"""
event.initialise_plugins()
self.after(0, self.run_after)
self.mainloop()
@event.register
def run_after(self) -> None:
"""
Run after the installer has been initialised, can be used to add plugins
:return:
"""
return None
# Menu bar
class Menu(tkinter.Menu):
def __init__(self, master):
super().__init__(master)
self.language = self.Language(self)
self.track_configuration = self.TrackConfiguration(self)
self.advanced = self.Advanced(self)
self.help = self.Help(self)
# Language menu
class Language(tkinter.Menu):
def __init__(self, master: tkinter.Menu):
super().__init__(master, tearoff=False)
master.add_cascade(label=_("LANGUAGE_SELECTION"), menu=self)
for file in Path("./assets/language/").iterdir():
self.add_command(label=json.loads(file.read_text(encoding="utf8"))["name"])
# Track configuration menu
class TrackConfiguration(tkinter.Menu):
def __init__(self, master: tkinter.Menu):
super().__init__(master, tearoff=False)
master.add_cascade(label=_("TRACK_CONFIGURATION"), menu=self)
self.add_command(label="Change configuration")
# Advanced menu
class Advanced(tkinter.Menu):
def __init__(self, master: tkinter.Menu):
super().__init__(master, tearoff=False)
master.add_cascade(label=_("ADVANCED_CONFIGURATION"), menu=self)
self.add_command(label="Debug mode")
# Help menu
class Help(tkinter.Menu):
def __init__(self, master: tkinter.Menu):
super().__init__(master, tearoff=False)
master.add_cascade(label="Help", menu=self)
self.add_command(label="Discord", command=lambda: webbrowser.open(discord_url))
self.add_command(label="Github Wiki", command=lambda: webbrowser.open(github_wiki_url))
# Select game frame
class SourceGame(ttk.LabelFrame):
def __init__(self, master: tkinter.Tk):
super().__init__(master, text="Original Game")
self.entry = ttk.Entry(self, width=50)
self.entry.grid(row=1, column=1, sticky="nsew")
self.button = ttk.Button(self, text="...", width=2, command=self.select)
self.button.grid(row=1, column=2, sticky="nsew")
def select(self) -> None:
"""
Select the source game
:return:
"""
path = Path(tkinter.filedialog.askopenfilename(
title=_("SELECT_SOURCE_GAME"),
filetypes=[(_("WII GAMES"), "*.iso *.wbfs *.dol")],
))
# if the user didn't select any file, return None
if not path.exists():
messagebox.showerror(_("ERROR"), _("ERROR_INVALID_SOURCE_GAME"))
return
self.set_path(path)
def set_path(self, path: Path) -> None:
"""
Set the source game path
:param path:
:return:
"""
self.entry.delete(0, tkinter.END)
self.entry.insert(0, str(path.absolute()))
self.master.destination_game.set_path(path.parent / "MKWF.iso")
# Select game destination frame
class DestinationGame(ttk.LabelFrame):
def __init__(self, master: tkinter.Tk):
super().__init__(master, text="Game Destination")
self.entry = ttk.Entry(self, width=50)
self.entry.grid(row=1, column=1, sticky="nsew")
self.button = ttk.Button(self, text="...", width=2, command=self.select)
self.button.grid(row=1, column=2, sticky="nsew")
def select(self) -> None:
"""
Select the source game
:return:
"""
path = Path(tkinter.filedialog.asksaveasfilename(
title=_("SELECT_DESTINATION_GAME"),
filetypes=[(_("WII GAMES"), "*.iso *.wbfs *.dol")],
))
path.parent.mkdir(mode=0o777, parents=True, exist_ok=True)
self.set_path(path)
def set_path(self, path: Path):
if not os.access(path.parent, os.W_OK):
messagebox.showwarning(_("WARNING"), _("WARNING_DESTINATION_GAME_NOT_WRITABLE"))
self.entry.delete(0, tkinter.END)
self.entry.insert(0, str(path.absolute()))
# Install button
class ButtonInstall(ttk.Button):
def __init__(self, master: tkinter.Tk):
super().__init__(master, text="Install", command=self.install)
def install(self):
# get space remaining on the C: drive
if shutil.disk_usage(".").free < minimum_space_available:
if not messagebox.askokcancel(_("WARNING"), _("WARNING_NOT_ENOUGH_SPACE_CONTINUE")): return
# Progress bar
class ProgressBar(ttk.LabelFrame):
def __init__(self, master: tkinter.Tk):
super().__init__(master)
# make the element fill the whole frame
self.columnconfigure(1, weight=1)
self.progress_bar = ttk.Progressbar(self, orient="horizontal")
self.progress_bar.grid(row=1, column=1, sticky="nsew")
self.description = ttk.Label(self, text="no process running", anchor="center", font=("TkDefaultFont", 10))
self.description.grid(row=2, column=1, sticky="nsew")
# Combobox to select the pack
class SelectPack(ttk.Combobox):
def __init__(self, master: tkinter.Tk):
super().__init__(master)
for pack in Path("./Pack/").iterdir():
self.insert(tkinter.END, pack.name)