mirror of
https://github.com/velopack/velopack.git
synced 2025-10-25 15:19:22 +00:00
185 lines
6.3 KiB
Python
185 lines
6.3 KiB
Python
import logging
|
|
import threading
|
|
import wx
|
|
|
|
import velopack
|
|
from _build_config import update_url
|
|
|
|
class BufferedLogHandler(logging.Handler):
|
|
"""Buffers log messages and provides access to them"""
|
|
def __init__(self):
|
|
super().__init__()
|
|
self.buffer = []
|
|
|
|
def emit(self, record):
|
|
msg = self.format(record)
|
|
self.buffer.append(msg)
|
|
|
|
def get_messages(self):
|
|
"""Get all buffered messages and clear the buffer"""
|
|
messages = self.buffer[:]
|
|
self.buffer.clear()
|
|
return messages
|
|
|
|
# Global buffered handler
|
|
log_handler = BufferedLogHandler()
|
|
|
|
class MainFrame(wx.Frame):
|
|
def __init__(self):
|
|
super().__init__(None, title="Velopack Sample", size=(600, 400))
|
|
|
|
# create velopacks update manager
|
|
self.update_manager = None
|
|
self.update_info = None
|
|
|
|
# Create main panel
|
|
panel = wx.Panel(self)
|
|
|
|
# Create buttons with minimum width to prevent text cutoff
|
|
self.check_btn = wx.Button(panel, label="Check", size=(150, -1))
|
|
self.download_btn = wx.Button(panel, label="Download", size=(150, -1))
|
|
self.apply_btn = wx.Button(panel, label="Apply", size=(150, -1))
|
|
|
|
# Start with Download and Apply disabled
|
|
self.download_btn.Disable()
|
|
self.apply_btn.Disable()
|
|
|
|
# Create log text control (multiline and read-only)
|
|
self.log_text = wx.TextCtrl(panel,
|
|
style=wx.TE_MULTILINE | wx.TE_READONLY)
|
|
|
|
# Bind button events
|
|
self.check_btn.Bind(wx.EVT_BUTTON, self.on_check)
|
|
self.download_btn.Bind(wx.EVT_BUTTON, self.on_download)
|
|
self.apply_btn.Bind(wx.EVT_BUTTON, self.on_apply)
|
|
|
|
# Layout
|
|
self.setup_layout(panel)
|
|
|
|
# Center the frame
|
|
self.Center()
|
|
|
|
# Start timer to check for log messages
|
|
self.timer = wx.Timer(self)
|
|
self.Bind(wx.EVT_TIMER, self.on_timer)
|
|
self.timer.Start(5)
|
|
|
|
logging.info("GUI initialized and ready")
|
|
|
|
def on_timer(self, event):
|
|
"""Check for new log messages and add them to text control"""
|
|
messages = log_handler.get_messages()
|
|
for msg in messages:
|
|
self.log_text.AppendText(f"{msg}\n")
|
|
|
|
def setup_layout(self, panel):
|
|
# Create sizers
|
|
main_sizer = wx.BoxSizer(wx.VERTICAL)
|
|
button_sizer = wx.BoxSizer(wx.HORIZONTAL)
|
|
|
|
# Add buttons to horizontal sizer
|
|
button_sizer.Add(self.check_btn, 0, wx.ALL, 5)
|
|
button_sizer.Add(self.download_btn, 0, wx.ALL, 5)
|
|
button_sizer.Add(self.apply_btn, 0, wx.ALL, 5)
|
|
|
|
# Add to main sizer
|
|
main_sizer.Add(button_sizer, 0, wx.ALL | wx.EXPAND, 10)
|
|
main_sizer.Add(self.log_text, 1, wx.ALL | wx.EXPAND, 10)
|
|
|
|
panel.SetSizer(main_sizer)
|
|
|
|
def on_check(self, event):
|
|
try:
|
|
self.update_manager = velopack.UpdateManager(update_url)
|
|
except Exception as e:
|
|
logging.error(f"Failed to initialize update manager: {e}")
|
|
return
|
|
self.update_info = self.update_manager.check_for_updates()
|
|
if self.update_info:
|
|
logging.info(f"Update available: {self.update_info}")
|
|
# Enable download and apply buttons when update is available
|
|
self.download_btn.Enable()
|
|
self.apply_btn.Enable()
|
|
else:
|
|
logging.info("No updates available")
|
|
# Keep buttons disabled if no update
|
|
self.download_btn.Disable()
|
|
self.apply_btn.Disable()
|
|
|
|
|
|
def on_download(self, event):
|
|
if not self.update_info:
|
|
logging.warning("No update information available. Please check first.")
|
|
return
|
|
|
|
# Disable buttons during download
|
|
self.download_btn.Disable()
|
|
self.apply_btn.Disable()
|
|
|
|
def progress_callback(progress):
|
|
# Update button text with progress percentage
|
|
wx.CallAfter(self.download_btn.SetLabel, f"Downloading... {progress}%")
|
|
|
|
def download_thread():
|
|
try:
|
|
# Store original button label
|
|
original_label = self.download_btn.GetLabel()
|
|
|
|
# Call download_updates with progress callback
|
|
self.update_manager.download_updates(self.update_info, progress_callback)
|
|
|
|
# Restore original button label when done
|
|
wx.CallAfter(self.download_btn.SetLabel, original_label)
|
|
wx.CallAfter(self.download_btn.Enable)
|
|
wx.CallAfter(self.apply_btn.Enable)
|
|
wx.CallAfter(logging.info, "Update downloaded successfully")
|
|
except Exception as e:
|
|
# Restore button label on error
|
|
wx.CallAfter(self.download_btn.SetLabel, "Download")
|
|
wx.CallAfter(self.download_btn.Enable)
|
|
wx.CallAfter(self.apply_btn.Enable)
|
|
wx.CallAfter(logging.error, f"Failed to download update: {e}")
|
|
|
|
# Start download in a separate thread
|
|
thread = threading.Thread(target=download_thread, daemon=True)
|
|
thread.start()
|
|
|
|
def on_apply(self, event):
|
|
if not self.update_info:
|
|
logging.warning("No update information available. Please check first.")
|
|
return
|
|
|
|
try:
|
|
self.update_manager.apply_updates_and_restart(self.update_info)
|
|
logging.info("Update applied successfully")
|
|
except Exception as e:
|
|
logging.error(f"Failed to apply update: {e}")
|
|
|
|
def setup_logging():
|
|
"""Setup logging to use buffered handler"""
|
|
logger = logging.getLogger()
|
|
|
|
# Remove existing handlers
|
|
for handler in logger.handlers[:]:
|
|
logger.removeHandler(handler)
|
|
|
|
# Setup our buffered handler
|
|
formatter = logging.Formatter('- %(levelname)s - %(message)s')
|
|
log_handler.setFormatter(formatter)
|
|
log_handler.setLevel(logging.INFO)
|
|
|
|
logger.addHandler(log_handler)
|
|
logger.setLevel(logging.INFO)
|
|
|
|
if __name__ == "__main__":
|
|
# Setup logging before velopack runs
|
|
setup_logging()
|
|
|
|
# Run velopack early
|
|
velopack.App().run()
|
|
|
|
# Create and run the wx app
|
|
app = wx.App(False)
|
|
frame = MainFrame()
|
|
frame.Show()
|
|
app.MainLoop() |