This commit introduces a new Tkinter-based GUI installer script (`installer/main.py`) that manages file extraction and shortcut creation. Additionally, a new file system access feature was added to the `ToolboxWindow` class, allowing users to open directories with platform-specific commands. Improvements also include platform-specific adjustments for Windows executables in the CMake configuration.
178 lines
6.5 KiB
Python
178 lines
6.5 KiB
Python
import base64
|
|
import os
|
|
from tkinter import Tk, Button, Label, Entry, filedialog, messagebox, StringVar, DoubleVar, Frame, Text
|
|
from tkinter.ttk import Progressbar, Style
|
|
|
|
# Base64-Strings für die Dateien (als Platzhalter)
|
|
exe_base64 = "..." # Base64-String der .exe
|
|
icon_base64 = "..." # Base64-String der .ico
|
|
|
|
|
|
def decode_base64_to_file(base64_str, output_path, progress_callback=None):
|
|
"""Decodes a Base64 string and writes it to a file."""
|
|
data = base64.b64decode(base64_str)
|
|
total_bytes = len(data)
|
|
chunk_size = 1024
|
|
with open(output_path, 'wb') as file:
|
|
for i in range(0, total_bytes, chunk_size):
|
|
file.write(data[i:i + chunk_size])
|
|
if progress_callback:
|
|
progress_callback(min((i + chunk_size) / total_bytes * 100, 100))
|
|
|
|
|
|
def update_progress(value):
|
|
"""Updates the progress bar."""
|
|
progress_var.set(value)
|
|
root.update_idletasks()
|
|
|
|
|
|
def select_directory():
|
|
"""Opens a directory selection dialog."""
|
|
directory = filedialog.askdirectory(
|
|
title="Select Output Directory",
|
|
initialdir=output_dir_var.get() or os.path.expandvars('%PROGRAMFILES(X86)%')
|
|
)
|
|
if directory:
|
|
os.makedirs(directory, exist_ok=True) # Create the folder if it doesn't exist
|
|
output_dir_var.set(directory)
|
|
|
|
|
|
def create_shortcut(target, shortcut_name, icon_path):
|
|
"""Creates shortcuts on Desktop and Startup folder."""
|
|
desktop = os.path.join(os.environ['USERPROFILE'], 'Desktop')
|
|
path = os.path.join(desktop, shortcut_name + ".lnk")
|
|
|
|
startup = os.path.join(os.getenv('APPDATA'), r'Microsoft\Windows\Start Menu\Programs\Startup')
|
|
startup_shortcut = os.path.join(startup, shortcut_name + ".lnk")
|
|
|
|
vbs_script = f'''
|
|
Set oWS = WScript.CreateObject("WScript.Shell")
|
|
sLinkFile = "{path}"
|
|
Set oLink = oWS.CreateShortcut(sLinkFile)
|
|
oLink.TargetPath = "{target}"
|
|
oLink.IconLocation = "{icon_path}"
|
|
oLink.Save
|
|
'''
|
|
startup_vbs_script = f'''
|
|
Set oWS = WScript.CreateObject("WScript.Shell")
|
|
sLinkFile = "{startup_shortcut}"
|
|
Set oLink = oWS.CreateShortcut(sLinkFile)
|
|
oLink.TargetPath = "{target}"
|
|
oLink.IconLocation = "{icon_path}"
|
|
oLink.Save
|
|
'''
|
|
|
|
for script, output in [(vbs_script, "create_shortcut.vbs"), (startup_vbs_script, "create_startup_shortcut.vbs")]:
|
|
with open(output, "w") as file:
|
|
file.write(script)
|
|
os.system(f"wscript {output}")
|
|
os.remove(output)
|
|
|
|
|
|
def extract_files():
|
|
"""Extracts the files to the selected directory and creates shortcuts."""
|
|
output_directory = output_dir_var.get()
|
|
if not output_directory:
|
|
messagebox.showerror("Error", "Please select a valid output directory.")
|
|
return
|
|
|
|
exe_path = os.path.join(output_directory, "application.exe")
|
|
icon_path = os.path.join(output_directory, "icon.ico")
|
|
|
|
try:
|
|
# Ensure the output directory exists
|
|
os.makedirs(output_directory, exist_ok=True)
|
|
|
|
# Decode and save files
|
|
decode_base64_to_file(exe_base64, exe_path, update_progress)
|
|
decode_base64_to_file(icon_base64, icon_path, update_progress)
|
|
|
|
# Create shortcuts
|
|
create_shortcut(exe_path, "DeinProgrammName", icon_path)
|
|
|
|
messagebox.showinfo("Success", "Installation abgeschlossen!")
|
|
except Exception as e:
|
|
messagebox.showerror("Error", f"Failed to extract files: {e}")
|
|
|
|
|
|
def show_readme():
|
|
"""Displays the final README page."""
|
|
readme_window = Frame(root, bg='#2e2e2e')
|
|
readme_window.pack(fill='both', expand=True)
|
|
Label(readme_window, text="Installation abgeschlossen!", bg="#2e2e2e", fg="white", font=("Helvetica", 16)).pack(pady=20)
|
|
readme_text = Text(readme_window, bg="#444", fg="white", wrap='word', height=10, width=50)
|
|
readme_text.insert('1.0', "Vielen Dank, dass Sie 'DeinProgrammName' installiert haben!\n\nWeitere Informationen finden Sie auf unserer Website.")
|
|
readme_text.configure(state='disabled')
|
|
readme_text.pack(pady=10)
|
|
Button(readme_window, text="Beenden", command=root.quit).pack(pady=10)
|
|
|
|
|
|
def next_page():
|
|
"""Handles the navigation between pages."""
|
|
global current_page
|
|
if current_page == 1:
|
|
setup_page_2()
|
|
elif current_page == 2:
|
|
extract_files()
|
|
setup_page_3()
|
|
|
|
|
|
def setup_page_1():
|
|
"""Sets up the welcome page."""
|
|
global current_page
|
|
current_page = 1
|
|
welcome_page = Frame(root, bg='#2e2e2e')
|
|
welcome_page.pack(fill='both', expand=True)
|
|
|
|
Label(welcome_page, text="Willkommen beim Installer!", bg="#2e2e2e", fg="white", font=("Helvetica", 16)).pack(pady=20)
|
|
Label(welcome_page, text="Klicken Sie auf 'Weiter', um fortzufahren.", bg="#2e2e2e", fg="white").pack(pady=10)
|
|
Button(welcome_page, text="Weiter", command=lambda: (welcome_page.pack_forget(), next_page())).pack()
|
|
|
|
|
|
def setup_page_2():
|
|
"""Sets up the installation folder selection page."""
|
|
global current_page
|
|
current_page = 2
|
|
folder_page = Frame(root, bg='#2e2e2e')
|
|
folder_page.pack(fill='both', expand=True)
|
|
|
|
Label(folder_page, text="Installationsordner wählen:", bg="#2e2e2e", fg="white").pack(pady=5)
|
|
Entry(folder_page, textvariable=output_dir_var, width=50).pack(pady=5)
|
|
Button(folder_page, text="Durchsuchen...", command=select_directory).pack(pady=5)
|
|
Button(folder_page, text="Weiter", command=lambda: (folder_page.pack_forget(), next_page())).pack()
|
|
|
|
|
|
def setup_page_3():
|
|
"""Sets up the installation progress page."""
|
|
global current_page
|
|
current_page = 3
|
|
progress_page = Frame(root, bg='#2e2e2e')
|
|
progress_page.pack(fill='both', expand=True)
|
|
|
|
Label(progress_page, text="Installation läuft...", bg="#2e2e2e", fg="white").pack(pady=20)
|
|
progress_bar = Progressbar(progress_page, orient='horizontal', length=400, variable=progress_var,
|
|
style='Horizontal.TProgressbar')
|
|
progress_bar.pack(pady=10)
|
|
Button(progress_page, text="Weiter", command=lambda: (progress_page.pack_forget(), show_readme())).pack()
|
|
|
|
|
|
# Tkinter Setup
|
|
root = Tk()
|
|
root.title("Installer")
|
|
root.geometry("500x350")
|
|
|
|
# Darkmode Style
|
|
style = Style(root)
|
|
style.theme_use('clam')
|
|
style.configure('TLabel', background='#2e2e2e', foreground='white', font=('Helvetica', 12))
|
|
style.configure('TButton', background='#444', foreground='white', font=('Helvetica', 10))
|
|
style.configure('Horizontal.TProgressbar', troughcolor='#444', background='#5a9')
|
|
root.configure(background='#2e2e2e')
|
|
|
|
output_dir_var = StringVar(value=os.path.join(os.environ['PROGRAMFILES(X86)'], "DeinProgrammName"))
|
|
progress_var = DoubleVar()
|
|
current_page = 0
|
|
|
|
setup_page_1()
|
|
root.mainloop()
|