diff --git a/pkg/xlsform-offline-win.spec b/pkg/xlsform-offline-win.spec index 41d4215..38af620 100644 --- a/pkg/xlsform-offline-win.spec +++ b/pkg/xlsform-offline-win.spec @@ -19,6 +19,7 @@ exe = EXE(pyz, a.zipfiles, a.datas, [('res\\about.html', os.getcwd() + '\\src\\res\\about.html', 'DATA')], + [('res\\update.html', os.getcwd() + '\\src\\res\\update.html', 'DATA')], [('pyxform\\validators\\odk_validate\\bin\\ODK_Validate.jar', validate_path, 'DATA')], [('pyxform\\iana_subtags.txt', iana_path, 'DATA')], name='ODK-XLSForm-Offline.exe', diff --git a/src/main.py b/src/main.py index 64e722b..af62d69 100755 --- a/src/main.py +++ b/src/main.py @@ -11,11 +11,14 @@ import wx import worker +import update_checker + # TODO pull out all strings # TODO why is the first button selected - TITLE = 'ODK XLSForm Offline' +VERSION = "2.0.0" + APP_QUIT = 1 APP_ABOUT = 2 @@ -23,6 +26,8 @@ MAIN_WINDOW_HEIGHT = 620 ABOUT_WINDOW_WIDTH = 360 ABOUT_WINDOW_HEIGHT = 365 +UPDATE_WINDOW_WIDTH = 360 +UPDATE_WINDOW_HEIGHT = 365 MAX_PATH_LENGTH = 45 HEADER_SPACER = 6 CHOOSE_BORDER = 5 @@ -34,6 +39,8 @@ MAIN_WINDOW_HEIGHT = 750 ABOUT_WINDOW_WIDTH = 360 ABOUT_WINDOW_HEIGHT = 315 + UPDATE_WINDOW_WIDTH = 360 + UPDATE_WINDOW_HEIGHT = 315 MAX_PATH_LENGTH = 40 HEADER_SPACER = 0 CHOOSE_BORDER = 1 @@ -44,6 +51,27 @@ WORKER_PROGRESS = 'WORKER_PROGRESS' WORKER_PROGRESS_SLEEP = .05 +class UpdateAvailableFrame(wx.Frame): + def __init__(self, parent, update_info): + wx.Frame.__init__(self, parent, wx.ID_ANY, title='Update ' + update_info['latest_version'] + ' available', + size=(UPDATE_WINDOW_WIDTH, UPDATE_WINDOW_HEIGHT), + style=wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX) + html = HtmlWindow(self) + html.SetStandardFonts() + update_html_path = '' + if getattr(sys, 'frozen', False): + update_html_path = os.path.join(sys._MEIPASS, 'res', 'update.html') + else: + update_html_path = os.path.join('src', 'res', 'update.html') + + update_html_text = '' + with open(update_html_path, 'r') as file: + update_html_text = file.read() + + filled_update_html_text = update_html_text.replace('@desc', update_info['update_desc']).replace( + '@download_url', update_info['download_url']).replace('@download_name', update_info['download_name']) + + html.SetPage(filled_update_html_text) class AboutFrame(wx.Frame): def __init__(self, parent): @@ -52,11 +80,20 @@ def __init__(self, parent): style=wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX) html = HtmlWindow(self) html.SetStandardFonts() - about = os.path.join('res','about.html') + about_html_path = os.path.join('res','about.html') + if getattr(sys, 'frozen', False): - html.LoadPage(os.path.join(sys._MEIPASS, about)) + about_html_path = os.path.join(sys._MEIPASS, about_html_path) else: - html.LoadPage(os.path.join('src', about)) + about_html_path = os.path.join('src', about_html_path) + + about_html_text = '' + with open(about_html_path, 'r') as file: + about_html_text = file.read() + + filled_about_html_text = about_html_text.replace('@version', VERSION) + + html.SetPage(filled_about_html_text) class HtmlWindow(wx.html.HtmlWindow): @@ -88,6 +125,7 @@ def __init__(self, parent, title): self.quit_menu_item = wx.MenuItem(self.file_menu, APP_QUIT, '&Quit\tCtrl+Q') self.about_menu_item = wx.MenuItem(self.help_menu, APP_ABOUT, '&About ' + TITLE) + self.update_window = None self.file_menu.Append(self.quit_menu_item) self.help_menu.Append(self.about_menu_item) @@ -222,6 +260,9 @@ def __init__(self, parent, title): self.Centre() self.Show() + update_checker.evt_update_check_done(self, self.check_update_and_show) + update_checker.UpdateChecker(self, VERSION).start() + @staticmethod def shorten_string(string, max_length): if len(string) >= max_length: @@ -290,6 +331,8 @@ def on_quit(self, e): self.Destroy() if self.about_window: self.about_window.Close() + if self.update_window: + self.update_window.Close() def on_about(self, e): if self.about_window: @@ -314,6 +357,15 @@ def on_progress(self, event): if self.result_thread is not None and self.result_thread.is_alive(): self.status_gauge.Pulse() + def check_update_and_show(self, event): + if self.update_window: + self.update_window.Close() + + if event.data['update_available']: + self.update_window = UpdateAvailableFrame(None, event.data) + self.update_window.Centre() + self.update_window.Show() + @staticmethod def is_java_installed(): diff --git a/src/res/about.html b/src/res/about.html index 91cae19..85ce110 100644 --- a/src/res/about.html +++ b/src/res/about.html @@ -14,7 +14,7 @@ ODK is a community-powered project and the community lives on the ODK Forum. Join the forum to get support, request features, meet other ODKers, and contribute to the project!