Skip to content

Commit

Permalink
[gui] Add GUI installation support (#15)
Browse files Browse the repository at this point in the history
* [gui] Add ltchiptool installation manager, show Python version in GUI

* [gui] Add draft installer window

* [gui] Add installer progress bar

* [gui] Support installation desktop shortcut, FTA and PATH

* [gui] Implement installer UI and worker thread
  • Loading branch information
kuba2k2 authored Dec 15, 2023
1 parent eedc2d9 commit e153832
Show file tree
Hide file tree
Showing 19 changed files with 1,221 additions and 57 deletions.
3 changes: 3 additions & 0 deletions gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,7 @@
from ltchiptool.gui import cli

if __name__ == "__main__":
from ltchiptool.util.ltim import LTIM

LTIM.get().is_gui_entrypoint = True
cli()
7 changes: 3 additions & 4 deletions ltchiptool/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,10 @@

from ltchiptool.util.cli import get_multi_command_class
from ltchiptool.util.logging import VERBOSE, LoggingHandler, log_setup_click_bars
from ltchiptool.util.ltim import LTIM
from ltchiptool.util.lvm import LVM
from ltchiptool.util.streams import LoggingStreamHook

from .version import get_version

COMMANDS = {
# compile commands
"elf2bin": "ltchiptool/commands/compile/elf2bin.py",
Expand Down Expand Up @@ -86,10 +85,10 @@
type=click.Path(exists=True, dir_okay=True),
)
@click.version_option(
get_version(),
LTIM.get_version_full(),
"-V",
"--version",
message="ltchiptool v%(version)s",
message="ltchiptool %(version)s",
)
@click.pass_context
def cli_entrypoint(
Expand Down
10 changes: 8 additions & 2 deletions ltchiptool/gui/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@


def cli():
from .__main__ import cli
import sys

cli()
from .__main__ import cli, install_cli

if len(sys.argv) > 1 and sys.argv[1] == "install":
sys.argv.pop(1)
install_cli()
else:
cli()
59 changes: 51 additions & 8 deletions ltchiptool/gui/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@

import sys
from logging import INFO, NOTSET, error, exception
from pathlib import Path

import click

from ltchiptool import get_version
from ltchiptool.util.logging import LoggingHandler
from ltchiptool.util.ltim import LTIM


def gui_entrypoint(*args, **kwargs):
def gui_entrypoint(install: bool, *args, **kwargs):
if sys.version_info < (3, 10, 0):
error("ltchiptool GUI requires Python 3.10 or newer")
exit(1)
Expand All @@ -23,13 +24,20 @@ def gui_entrypoint(*args, **kwargs):

app = wx.App()
try:
from .main import MainFrame

if LoggingHandler.get().level == NOTSET:
LoggingHandler.get().level = INFO
frm = MainFrame(None, title=f"ltchiptool v{get_version()}")
frm.init_params = kwargs
frm.Show()

if not install:
from .main import MainFrame

frm = MainFrame(None, title=f"ltchiptool {LTIM.get_version_full()}")
frm.init_params = kwargs
frm.Show()
else:
from .install import InstallFrame

frm = InstallFrame(install_kwargs=kwargs, parent=None)
frm.Show()
app.MainLoop()
except Exception as e:
LoggingHandler.get().exception_hook = None
Expand All @@ -47,7 +55,42 @@ def gui_entrypoint(*args, **kwargs):
@click.argument("FILE", type=str, required=False)
def cli(*args, **kwargs):
try:
gui_entrypoint(*args, **kwargs)
gui_entrypoint(install=False, *args, **kwargs)
except Exception as e:
exception(None, exc_info=e)
exit(1)


@click.command(help="Start the installer")
@click.argument(
"out_path",
type=click.Path(
file_okay=False,
dir_okay=True,
writable=True,
resolve_path=True,
path_type=Path,
),
)
@click.option(
"--shortcut",
type=click.Choice(["private", "public"]),
help="Create a desktop shortcut",
)
@click.option(
"--fta",
type=str,
multiple=True,
help="File extensions to associate with ltchiptool",
)
@click.option(
"--add-path",
is_flag=True,
help="Add to system PATH",
)
def install_cli(*args, **kwargs):
try:
gui_entrypoint(install=True, *args, **kwargs)
except Exception as e:
exception(None, exc_info=e)
exit(1)
Expand Down
87 changes: 87 additions & 0 deletions ltchiptool/gui/install.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# Copyright (c) Kuba Szczodrzyński 2023-12-14.

from logging import INFO

import wx
import wx.xrc

from ltchiptool.util.logging import LoggingHandler
from ltchiptool.util.ltim import LTIM

from .base.window import BaseWindow
from .panels.log import LogPanel
from .utils import load_xrc_file
from .work.base import BaseThread
from .work.install import InstallThread


# noinspection PyPep8Naming
class InstallFrame(wx.Frame, BaseWindow):
failed: bool = False
finished: bool = False

def __init__(self, install_kwargs: dict, *args, **kw):
super().__init__(*args, **kw)

xrc = LTIM.get().get_gui_resource("ltchiptool.xrc")
icon = LTIM.get().get_gui_resource("ltchiptool.ico")
self.Xrc = load_xrc_file(xrc)

LoggingHandler.get().level = INFO
LoggingHandler.get().exception_hook = self.ShowExceptionMessage

self.Log = LogPanel(parent=self, frame=self)
# noinspection PyTypeChecker
self.Log.OnDonateClose(None)

self.install_kwargs = install_kwargs

self.Bind(wx.EVT_SHOW, self.OnShow)
self.Bind(wx.EVT_CLOSE, self.OnClose)

self.SetTitle("Installing ltchiptool")
self.SetIcon(wx.Icon(str(icon), wx.BITMAP_TYPE_ICO))
self.SetSize((1000, 400))
self.SetMinSize((600, 200))
self.Center()

def ShowExceptionMessage(self, e, msg):
self.failed = True
self.finished = True
wx.MessageBox(
message="Installation failed!\n\nRefer to the log window for details.",
caption="Error",
style=wx.ICON_ERROR,
)

def OnShow(self, *_):
self.InitWindow(self)
thread = InstallThread(**self.install_kwargs)
thread.daemon = True
self.StartWork(thread)

def OnWorkStopped(self, t: BaseThread):
if self.failed:
return
wx.MessageBox(
message="Installation finished\n\nClick OK to close the installer",
caption="Success",
style=wx.ICON_INFORMATION,
)
self.Close()

def OnClose(self, *_):
if self.finished:
self.Destroy()
return
if (
wx.MessageBox(
message="Do you want to cancel the installation process?",
caption="Installation in progress",
style=wx.ICON_QUESTION | wx.YES_NO,
)
!= wx.YES
):
return
self.StopWork(InstallThread)
self.Destroy()
Loading

0 comments on commit e153832

Please sign in to comment.