From 65eec114ae0581e0cb1a4b21f4e6ec9fb0837d2e Mon Sep 17 00:00:00 2001 From: Alexis Delhaie Date: Sat, 19 Dec 2020 22:10:10 +0100 Subject: [PATCH] Fix Window freezing while downloading --- main.py | 167 ++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 107 insertions(+), 60 deletions(-) diff --git a/main.py b/main.py index fbeafc6..315d4e2 100644 --- a/main.py +++ b/main.py @@ -3,12 +3,13 @@ import os import shutil import subprocess import sys +from threading import Thread import requests import wx from wx import Size, Point -## Installer configuration +# Installer configuration REPO_URL = "https://alexisdelhaie.ovh/dlcenter/chronos-repo/installer/" VERSION_FILE = "version" COMPANY_NAME = "alexlegarnd" @@ -23,6 +24,11 @@ FILES = ["libeay32.dll", "ssleay32.dll", "7z.dll", EXECUTABLE] WINDOW_TITLE = "Chronos Installer" +EVT_START_ID = wx.Window.NewControlId() +EVT_UPDATE_ID = wx.Window.NewControlId() +EVT_END_ID = wx.Window.NewControlId() + + def create_install_folder(): company_directory = "{}\\{}".format(os.getenv('APPDATA'), COMPANY_NAME) if not os.path.exists(company_directory): @@ -31,20 +37,6 @@ def create_install_folder(): os.mkdir(INSTALL_FOLDER) -def download_file_from_repo(filename, dlg): - url = "{}{}".format(REPO_URL, filename) - with open("{}\\{}".format(INSTALL_FOLDER, filename), 'wb') as f: - response = requests.get(url, stream=True) - total_length = response.headers.get('content-length') - dlg.set_total(filename, int(total_length)) - if total_length is None: # no content length header - f.write(response.content) - else: - for data in response.iter_content(chunk_size=4096): - f.write(data) - dlg.update_progress(len(data)) - - def get_version_from_repo(): url = "{}{}".format(REPO_URL, VERSION_FILE) r = requests.get(url, allow_redirects=True) @@ -72,7 +64,19 @@ class MyApplication(wx.App): def OnInit(self): self.SetAppName(WINDOW_TITLE) if is_admin(): - self.main() + version = get_version_from_repo() + create_install_folder() + if get_installed_version() != version: + dlg = MyDialog(None, -1, WINDOW_TITLE, version, Size(400, 120)) + dlg.ShowModal() + dlg.Destroy() + if os.path.exists(EXECUTABLE_PATH): + subprocess.Popen([EXECUTABLE_PATH], cwd=INSTALL_FOLDER) + else: + dlg = wx.MessageDialog(None, "Installer executable not found", + WINDOW_TITLE, style=wx.OK | wx.ICON_HAND) + dlg.ShowModal() + dlg.Destroy() else: dlg = wx.MessageDialog(None, "This application requires administrative privileges to run", WINDOW_TITLE, style=wx.OK | wx.ICON_HAND) @@ -80,29 +84,41 @@ class MyApplication(wx.App): dlg.Destroy() return True - def main(self): - version = get_version_from_repo() - create_install_folder() + +class MyDialog(wx.Dialog): + + def __init__(self, parent, i, title, version, size=wx.DefaultSize): + wx.Dialog.__init__(self) + self.Create(parent, i, title, wx.DefaultPosition, size, wx.DEFAULT_DIALOG_STYLE, WINDOW_TITLE) + self.Centre() + self.panel = wx.Panel(self) + self.status = wx.StaticText(self.panel, label="Starting...", pos=Point(17, 10)) + self.progress = wx.Gauge(self.panel, -1, size=Size(350, 25), pos=Point(17, 40)) + self.pg = 0 + self.total = 100 + self.filename = "no_name_file" + self.Connect(-1, -1, EVT_START_ID, self.set_total) + self.Connect(-1, -1, EVT_UPDATE_ID, self.update_progress) + self.Connect(-1, -1, EVT_END_ID, self.end) self.clean() - if get_installed_version() != version: - dlg = MyDialog(None, -1, WINDOW_TITLE, Size(400, 120)) - dlg.Show() - self.clean_folder(INSTALL_FOLDER) - for file in FILES: - download_file_from_repo(file, dlg) - if os.path.exists(INSTALLED_VERSION_PATH): - os.remove(INSTALLED_VERSION_PATH) - file = open(INSTALLED_VERSION_PATH, "w") - file.write(version) - file.close() - dlg.Destroy() - if os.path.exists(EXECUTABLE_PATH): - subprocess.Popen([EXECUTABLE_PATH], cwd=INSTALL_FOLDER) - else: - dlg = wx.MessageDialog(None, "Installer executable not found", - WINDOW_TITLE, style=wx.OK | wx.ICON_HAND) - dlg.ShowModal() - dlg.Destroy() + self.clean_folder(INSTALL_FOLDER) + self.handler = WorkerThread(version, self) + + def update_progress(self, event): + self.pg += event.value + percentage = (self.pg / self.total) * 100 + self.status.SetLabelText("Downloading {} ({}%)".format(self.filename, int(percentage))) + self.progress.SetValue(self.pg) + + def set_total(self, event): + self.filename = event.filename + self.pg = 0 + self.total = event.total + self.progress.SetValue(0) + self.progress.SetRange(event.total) + + def end(self, event): + self.Close() def clean_folder(self, path): if os.path.exists(path): @@ -130,31 +146,62 @@ class MyApplication(wx.App): self.clean_folder(INSTALL_FOLDER) -class MyDialog(wx.Dialog): +class PercentageInfo(wx.PyEvent): - def __init__(self, parent, i, title, size=wx.DefaultSize): - wx.Dialog.__init__(self) - self.Create(parent, i, title, wx.DefaultPosition, size, wx.DEFAULT_DIALOG_STYLE, WINDOW_TITLE) - self.Centre() - self.panel = wx.Panel(self) - self.status = wx.StaticText(self.panel, label="-------------------------------------------", pos=Point(17, 10)) - self.progress = wx.Gauge(self.panel, -1, size=Size(350, 25), pos=Point(17, 40)) - self.pg = 0 - self.total = 100 - self.filename = "no_name_file" - - def update_progress(self, value): - self.pg += value - percentage = (self.pg / self.total) * 100 - self.status.SetLabelText("Downloading {} ({}%)".format(self.filename, int(percentage))) - self.progress.SetValue(self.pg) - - def set_total(self, filename, total): + def __init__(self, filename, total): + super().__init__() + self.SetEventType(EVT_START_ID) self.filename = filename - self.pg = 0 self.total = total - self.progress.SetValue(0) - self.progress.SetRange(total) + + +class UpdatePercentage(wx.PyEvent): + + def __init__(self, value): + super().__init__() + self.SetEventType(EVT_UPDATE_ID) + self.value = value + + +class ProcessTerminated(wx.PyEvent): + + def __init__(self): + super().__init__() + self.SetEventType(EVT_END_ID) + + +class WorkerThread(Thread): + + def __init__(self, version, dlg): + Thread.__init__(self) + self.dlg = dlg + self.version = version + self.start() + + def run(self): + try: + for file in FILES: + self.download_file_from_repo(file) + if os.path.exists(INSTALLED_VERSION_PATH): + os.remove(INSTALLED_VERSION_PATH) + file = open(INSTALLED_VERSION_PATH, "w") + file.write(self.version) + file.close() + finally: + wx.PostEvent(self.dlg, ProcessTerminated()) + + def download_file_from_repo(self, filename): + url = "{}{}".format(REPO_URL, filename) + with open("{}\\{}".format(INSTALL_FOLDER, filename), 'wb') as f: + response = requests.get(url, stream=True) + total_length = response.headers.get('content-length') + wx.PostEvent(self.dlg, PercentageInfo(filename, int(total_length))) + if total_length is None: # no content length header + f.write(response.content) + else: + for data in response.iter_content(chunk_size=4096): + f.write(data) + wx.PostEvent(self.dlg, UpdatePercentage(len(data))) def main():