mirror of
https://github.com/Faraphel/Atlas-Install.git
synced 2025-07-02 02:38:30 +02:00
added permissions check
This commit is contained in:
parent
2f7f0ad5bf
commit
8d6141703b
9 changed files with 150 additions and 31 deletions
|
@ -1,6 +1,10 @@
|
|||
{
|
||||
"name": "English",
|
||||
"translation": {
|
||||
"INSTALLER_TITLE": "MKWF-Install"
|
||||
"INSTALLER_TITLE": "MKWF-Install",
|
||||
"LANGUAGE_SELECTION": "Language",
|
||||
"TRACK_CONFIGURATION": "Track Configuration",
|
||||
"ADVANCED_CONFIGURATION": "Advanced",
|
||||
"HELP": "Help"
|
||||
}
|
||||
}
|
|
@ -1,6 +1,10 @@
|
|||
{
|
||||
"name": "Français",
|
||||
"translation": {
|
||||
|
||||
"INSTALLER_TITLE": "MKWF-Install",
|
||||
"LANGUAGE_SELECTION": "Langue",
|
||||
"TRACK_CONFIGURATION": "Configuration des courses",
|
||||
"ADVANCED_CONFIGURATION": "Avancée",
|
||||
"HELP": "Aide"
|
||||
}
|
||||
}
|
7
main.pyw
7
main.pyw
|
@ -1,3 +1,8 @@
|
|||
from source.gui import install
|
||||
import sys
|
||||
|
||||
install.Window().mainloop()
|
||||
# this allows every variable to be accessible from other files, useful for the plugins
|
||||
self = sys.modules[__name__]
|
||||
|
||||
self.window = install.Window()
|
||||
self.window.run()
|
||||
|
|
|
@ -1,10 +1,22 @@
|
|||
from source import event
|
||||
import tkinter
|
||||
import sys
|
||||
|
||||
|
||||
@event.on("source.gui.install.Window.__init__")
|
||||
def test_button(master):
|
||||
tkinter.Button(master, text="test des plugins", command=lambda: print("test")).grid(
|
||||
@event.on("source.gui.install.Window.run_after")
|
||||
def test_button():
|
||||
"""
|
||||
Test function for the plugins
|
||||
:return:
|
||||
"""
|
||||
|
||||
# get the main window from the main module
|
||||
window = sys.modules["__main__"].window
|
||||
|
||||
# get the install button from the main window
|
||||
window.button_install.config(text="installation plugins")
|
||||
|
||||
# add a custom button on the main window
|
||||
tkinter.Button(window, text="test des plugins", command=lambda: print("test")).grid(
|
||||
row=10, column=1, sticky="nsew"
|
||||
)
|
||||
print("I have been called")
|
||||
)
|
4
setup.py
4
setup.py
|
@ -1,6 +1,6 @@
|
|||
from cx_Freeze import setup, Executable
|
||||
import sys
|
||||
import json
|
||||
import source
|
||||
|
||||
include_files = [
|
||||
"./LICENSE",
|
||||
|
@ -25,7 +25,7 @@ options = {
|
|||
setup(
|
||||
options=options,
|
||||
name='MKWF-Install',
|
||||
version="0.12",
|
||||
version=".".join(source.__version__),
|
||||
url='https://github.com/Faraphel/MKWF-Install',
|
||||
license='Apache-2.0',
|
||||
author='Faraphel',
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
__version__ = (0, 12, 0)
|
||||
__author__ = 'Faraphel'
|
||||
|
||||
|
||||
discord_url = "https://discord.gg/HEYW5v8ZCd"
|
||||
github_wiki_url = "https://github.com/Faraphel/MKWF-Install/wiki/help"
|
||||
|
||||
Ko = 1_000
|
||||
Mo = 1_000 * Ko
|
||||
Go = 1_000 * Mo
|
||||
|
||||
minimum_space_available = 15*Go
|
|
@ -2,11 +2,11 @@ from types import FunctionType
|
|||
from pathlib import Path
|
||||
import sys
|
||||
|
||||
# using this self variable allow us to keep the events in the whole module
|
||||
self = sys.modules[__name__]
|
||||
self.events = {}
|
||||
|
||||
|
||||
# register the function to the event
|
||||
def on(event_name: str):
|
||||
"""
|
||||
Register the function to be called when the event is called.
|
||||
|
@ -23,7 +23,6 @@ def on(event_name: str):
|
|||
return decorator
|
||||
|
||||
|
||||
# register all the events at the end of the function
|
||||
def register(func: FunctionType):
|
||||
"""
|
||||
Register the function as an event.
|
||||
|
@ -39,7 +38,6 @@ def register(func: FunctionType):
|
|||
return wrapper
|
||||
|
||||
|
||||
# call all the events of the event_name
|
||||
def call_event(event_name: str, *args, **kwargs) -> None:
|
||||
"""
|
||||
Call all the events associated with the event_name.
|
||||
|
@ -47,9 +45,13 @@ def call_event(event_name: str, *args, **kwargs) -> None:
|
|||
:return:
|
||||
"""
|
||||
for func in self.events.get(event_name, []):
|
||||
func(*args, **kwargs)
|
||||
func()
|
||||
|
||||
|
||||
# execute all scripts in the ./plugins/ directory that don't start with an underscore
|
||||
for file in Path("./plugins/").rglob("[!_]*.py"):
|
||||
exec(file.read_text(encoding="utf8"), globals())
|
||||
def initialise_plugins() -> None:
|
||||
"""
|
||||
Execute all the scripts in the ./plugins/ directory that don't start with an underscore.
|
||||
:return:
|
||||
"""
|
||||
for file in Path("./plugins/").rglob("[!_]*.py"):
|
||||
exec(file.read_text(encoding="utf8"), globals())
|
||||
|
|
|
@ -1,16 +1,20 @@
|
|||
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):
|
||||
@event.register
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
|
@ -38,6 +42,22 @@ class Window(tkinter.Tk):
|
|||
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):
|
||||
|
@ -54,7 +74,7 @@ class Menu(tkinter.Menu):
|
|||
def __init__(self, master: tkinter.Menu):
|
||||
super().__init__(master, tearoff=False)
|
||||
|
||||
master.add_cascade(label="Language", menu=self)
|
||||
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"])
|
||||
|
@ -64,7 +84,7 @@ class Menu(tkinter.Menu):
|
|||
def __init__(self, master: tkinter.Menu):
|
||||
super().__init__(master, tearoff=False)
|
||||
|
||||
master.add_cascade(label="Track Configuration", menu=self)
|
||||
master.add_cascade(label=_("TRACK_CONFIGURATION"), menu=self)
|
||||
self.add_command(label="Change configuration")
|
||||
|
||||
# Advanced menu
|
||||
|
@ -72,7 +92,7 @@ class Menu(tkinter.Menu):
|
|||
def __init__(self, master: tkinter.Menu):
|
||||
super().__init__(master, tearoff=False)
|
||||
|
||||
master.add_cascade(label="Advanced", menu=self)
|
||||
master.add_cascade(label=_("ADVANCED_CONFIGURATION"), menu=self)
|
||||
self.add_command(label="Debug mode")
|
||||
|
||||
# Help menu
|
||||
|
@ -81,8 +101,8 @@ class Menu(tkinter.Menu):
|
|||
super().__init__(master, tearoff=False)
|
||||
|
||||
master.add_cascade(label="Help", menu=self)
|
||||
self.add_command(label="Discord")
|
||||
self.add_command(label="Github Wiki")
|
||||
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
|
||||
|
@ -93,7 +113,35 @@ class SourceGame(ttk.LabelFrame):
|
|||
self.entry = ttk.Entry(self, width=50)
|
||||
self.entry.grid(row=1, column=1, sticky="nsew")
|
||||
|
||||
ttk.Button(self, text="...", width=2).grid(row=1, column=2, 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
|
||||
|
@ -104,7 +152,29 @@ class DestinationGame(ttk.LabelFrame):
|
|||
self.entry = ttk.Entry(self, width=50)
|
||||
self.entry.grid(row=1, column=1, sticky="nsew")
|
||||
|
||||
ttk.Button(self, text="...", width=2).grid(row=1, column=2, 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
|
||||
|
@ -113,18 +183,23 @@ class ButtonInstall(ttk.Button):
|
|||
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.Frame):
|
||||
class ProgressBar(ttk.LabelFrame):
|
||||
def __init__(self, master: tkinter.Tk):
|
||||
super().__init__(master)
|
||||
|
||||
self.progress_bar = ttk.Progressbar(self)
|
||||
# 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 = tkinter.Label(self, text="test")
|
||||
self.description = ttk.Label(self, text="no process running", anchor="center", font=("TkDefaultFont", 10))
|
||||
self.description.grid(row=2, column=1, sticky="nsew")
|
||||
|
||||
|
||||
|
|
|
@ -5,5 +5,10 @@ from pathlib import Path
|
|||
language_data = json.loads(Path("./assets/language/en.json").read_text(encoding="utf8"))
|
||||
|
||||
|
||||
def translate(*text):
|
||||
def translate(*text) -> str:
|
||||
"""
|
||||
Translate a text to the loaded language.
|
||||
:param text: list of text to translate
|
||||
:return: translated text
|
||||
"""
|
||||
return "".join([language_data["translation"].get(word, word) for word in text])
|
||||
|
|
Loading…
Reference in a new issue