From 04daed9c331dcefc1f52fa3fda619c6f470c424c Mon Sep 17 00:00:00 2001 From: Khaja Nizamuddin Date: Wed, 31 Jul 2019 21:04:34 +0530 Subject: [PATCH 01/14] update popup works --- requirements.txt | 2 + src/main.py | 201 ++++++++++++++++++++++++++++++++++---------- src/res/update.html | 15 ++++ 3 files changed, 175 insertions(+), 43 deletions(-) create mode 100644 src/res/update.html diff --git a/requirements.txt b/requirements.txt index c843ff5..35fd5d9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,6 @@ # macOS: Use the default Python. virtualenvs will not work. + pyinstaller wxpython pyxform +packaging diff --git a/src/main.py b/src/main.py index 64e722b..9b75bd1 100755 --- a/src/main.py +++ b/src/main.py @@ -11,10 +11,16 @@ import wx import worker +import requests +from packaging import version +import threading + # TODO pull out all strings # TODO why is the first button selected TITLE = 'ODK XLSForm Offline' +TITLE = 'ODK XLSForm Offline ' + VERSION +GITHUB_RELEASES_API = "https://api.github.com/repos/opendatakit/xlsform-offline/releases/latest" APP_QUIT = 1 APP_ABOUT = 2 @@ -22,7 +28,9 @@ MAIN_WINDOW_WIDTH = 475 MAIN_WINDOW_HEIGHT = 620 ABOUT_WINDOW_WIDTH = 360 -ABOUT_WINDOW_HEIGHT = 365 +ABOUT_WINDOW_HEIGHT = 335 +UPDATE_WINDOW_WIDTH = 330 +UPDATE_WINDOW_HEIGHT = 135 MAX_PATH_LENGTH = 45 HEADER_SPACER = 6 CHOOSE_BORDER = 5 @@ -33,7 +41,9 @@ MAIN_WINDOW_WIDTH = 500 MAIN_WINDOW_HEIGHT = 750 ABOUT_WINDOW_WIDTH = 360 - ABOUT_WINDOW_HEIGHT = 315 + ABOUT_WINDOW_HEIGHT = 290 + UPDATE_WINDOW_WIDTH = 330 + UPDATE_WINDOW_HEIGHT = 100 MAX_PATH_LENGTH = 40 HEADER_SPACER = 0 CHOOSE_BORDER = 1 @@ -44,6 +54,62 @@ WORKER_PROGRESS = 'WORKER_PROGRESS' WORKER_PROGRESS_SLEEP = .05 +OS_MAP = { + 'win32': 'windows', + 'darwin': 'macos' +} + + +class UpdateChecker(threading.Thread): + + def get_update_information(self): + response = requests.get(GITHUB_RELEASES_API) + if response.status_code == 200: + json_response = response.json() + latest_version = json_response["tag_name"] + print(latest_version) + if version.parse(latest_version[1:]) > version.parse(VERSION[1:]): + download_url = '' + download_name = '' + for asset in json_response['assets']: + if OS_MAP[sys.platform] in asset['name'].lower(): + download_url = asset['browser_download_url'] + download_name = asset['name'] + + return { + 'update_available': True, + 'latest_version': latest_version, + 'download_url': download_url, + 'download_name': download_name + } + else: + return { + 'update_available': False + } + + +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('@latest_version', update_info['latest_version']).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,7 +118,7 @@ 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 = os.path.join('res', 'about.html') if getattr(sys, 'frozen', False): html.LoadPage(os.path.join(sys._MEIPASS, about)) else: @@ -67,7 +133,8 @@ def OnLinkClicked(self, link): class MainFrame(wx.Frame): def __init__(self, parent, title): super(MainFrame, self).__init__(parent, title=title, - size=(MAIN_WINDOW_WIDTH, MAIN_WINDOW_HEIGHT), + size=(MAIN_WINDOW_WIDTH, + MAIN_WINDOW_HEIGHT), style=wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX) self.input_file_path = u'' self.output_folder_path = u'' @@ -81,13 +148,16 @@ def __init__(self, parent, title): self.progress_thread = None self.about_window = None + self.update_window = None self.menu_bar = wx.MenuBar() self.file_menu = wx.Menu() self.help_menu = wx.Menu() - 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.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.file_menu.Append(self.quit_menu_item) self.help_menu.Append(self.about_menu_item) @@ -114,20 +184,26 @@ def __init__(self, parent, title): # header self.header_box_sizer = wx.BoxSizer(wx.HORIZONTAL) self.header_box_sizer.AddStretchSpacer() - self.header_box_sizer.Add(self.about_button, proportion=0, flag=wx.LEFT | wx.RIGHT, border=5) - self.header_box_sizer.Add(self.quit_button, proportion=0, flag=wx.LEFT | wx.RIGHT, border=5) + self.header_box_sizer.Add( + self.about_button, proportion=0, flag=wx.LEFT | wx.RIGHT, border=5) + self.header_box_sizer.Add( + self.quit_button, proportion=0, flag=wx.LEFT | wx.RIGHT, border=5) # choose input file self.choose_input_static_box = wx.StaticBox(self.parent_panel, label='1. Choose XLSForm (.xls or .xlsx) for conversion') - self.choose_input_static_box_sizer = wx.StaticBoxSizer(self.choose_input_static_box, wx.HORIZONTAL) + self.choose_input_static_box_sizer = wx.StaticBoxSizer( + self.choose_input_static_box, wx.HORIZONTAL) - self.choose_file_button = wx.Button(self.parent_panel, label='Choose file...') + self.choose_file_button = wx.Button( + self.parent_panel, label='Choose file...') self.choose_file_button.Bind(wx.EVT_BUTTON, self.on_open_file) - self.chosen_file_text = wx.StaticText(self.parent_panel, label='', size=(-1, -1)) + self.chosen_file_text = wx.StaticText( + self.parent_panel, label='', size=(-1, -1)) self.choose_file_box_sizer = wx.BoxSizer(wx.HORIZONTAL) - self.choose_file_box_sizer.Add(self.choose_file_button, proportion=0, flag=wx.LEFT | wx.RIGHT, border=0) + self.choose_file_box_sizer.Add( + self.choose_file_button, proportion=0, flag=wx.LEFT | wx.RIGHT, border=0) self.choose_file_box_sizer.AddSpacer(CHOOSE_SPACER) self.choose_file_box_sizer.Add(self.chosen_file_text, proportion=1, flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.TOP, @@ -138,15 +214,20 @@ def __init__(self, parent, title): # choose output folder self.choose_folder_label = '2. Choose location for output file(s)' - self.choose_output_static_box = wx.StaticBox(self.parent_panel, label=self.choose_folder_label) - self.choose_output_static_box_sizer = wx.StaticBoxSizer(self.choose_output_static_box, wx.HORIZONTAL) + self.choose_output_static_box = wx.StaticBox( + self.parent_panel, label=self.choose_folder_label) + self.choose_output_static_box_sizer = wx.StaticBoxSizer( + self.choose_output_static_box, wx.HORIZONTAL) - self.choose_folder_button = wx.Button(self.parent_panel, label='Choose location...') + self.choose_folder_button = wx.Button( + self.parent_panel, label='Choose location...') self.choose_folder_button.Bind(wx.EVT_BUTTON, self.on_open_folder) - self.chosen_folder_text = wx.StaticText(self.parent_panel, label='', size=(-1, -1)) + self.chosen_folder_text = wx.StaticText( + self.parent_panel, label='', size=(-1, -1)) self.choose_folder_box_sizer = wx.BoxSizer(wx.HORIZONTAL) - self.choose_folder_box_sizer.Add(self.choose_folder_button, proportion=0, flag=wx.LEFT | wx.RIGHT, border=0) + self.choose_folder_box_sizer.Add( + self.choose_folder_button, proportion=0, flag=wx.LEFT | wx.RIGHT, border=0) self.choose_folder_box_sizer.AddSpacer(CHOOSE_SPACER) self.choose_folder_box_sizer.Add(self.chosen_folder_text, proportion=1, flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.TOP, @@ -156,37 +237,50 @@ def __init__(self, parent, title): border=5) # set conversion options - self.set_options_static_box = wx.StaticBox(self.parent_panel, label='3. Set conversion options') - self.set_options_static_box_sizer = wx.StaticBoxSizer(self.set_options_static_box, wx.VERTICAL) + self.set_options_static_box = wx.StaticBox( + self.parent_panel, label='3. Set conversion options') + self.set_options_static_box_sizer = wx.StaticBoxSizer( + self.set_options_static_box, wx.VERTICAL) self.overwrite_label = 'Overwrite existing output file(s)' - self.overwrite_checkbox = wx.CheckBox(self.parent_panel, label=self.overwrite_label, size=(-1, -1)) + self.overwrite_checkbox = wx.CheckBox( + self.parent_panel, label=self.overwrite_label, size=(-1, -1)) self.overwrite_checkbox.SetValue(self.overwrite) - self.Bind(wx.EVT_CHECKBOX, self.toggle_overwrite, id=self.overwrite_checkbox.GetId()) + self.Bind(wx.EVT_CHECKBOX, self.toggle_overwrite, + id=self.overwrite_checkbox.GetId()) self.validate_label = 'Validate converted XForm with ODK Validate' if self.is_java_installed(): self.validate = True - self.validate_checkbox = wx.CheckBox(self.parent_panel, label=self.validate_label, size=(-1, -1)) - self.Bind(wx.EVT_CHECKBOX, self.toggle_validate, id=self.validate_checkbox.GetId()) + self.validate_checkbox = wx.CheckBox( + self.parent_panel, label=self.validate_label, size=(-1, -1)) + self.Bind(wx.EVT_CHECKBOX, self.toggle_validate, + id=self.validate_checkbox.GetId()) else: self.validate = False - self.validate_checkbox = wx.CheckBox(self.parent_panel, label=self.validate_label + ' (Requires Java)') + self.validate_checkbox = wx.CheckBox( + self.parent_panel, label=self.validate_label + ' (Requires Java)') self.validate_checkbox.Disable() - self.Bind(wx.EVT_CHECKBOX, self.toggle_validate, id=self.validate_checkbox.GetId()) + self.Bind(wx.EVT_CHECKBOX, self.toggle_validate, + id=self.validate_checkbox.GetId()) self.validate_checkbox.SetValue(self.validate) - self.set_options_static_box_sizer.Add(self.overwrite_checkbox, flag=wx.LEFT | wx.TOP, border=5) + self.set_options_static_box_sizer.Add( + self.overwrite_checkbox, flag=wx.LEFT | wx.TOP, border=5) self.set_options_static_box_sizer.AddStretchSpacer() - self.set_options_static_box_sizer.Add(self.validate_checkbox, flag=wx.LEFT | wx.TOP, border=5) + self.set_options_static_box_sizer.Add( + self.validate_checkbox, flag=wx.LEFT | wx.TOP, border=5) self.set_options_static_box_sizer.AddStretchSpacer() self.set_options_static_box_sizer.AddSpacer(OPTIONS_SPACER) # start conversion - self.start_conversion_static_box = wx.StaticBox(self.parent_panel, label='4. Run conversion') - self.start_conversion_box_sizer = wx.StaticBoxSizer(self.start_conversion_static_box, wx.VERTICAL) + self.start_conversion_static_box = wx.StaticBox( + self.parent_panel, label='4. Run conversion') + self.start_conversion_box_sizer = wx.StaticBoxSizer( + self.start_conversion_static_box, wx.VERTICAL) - self.status_text_ctrl = wx.TextCtrl(self.parent_panel, size=(-1, 200), style=wx.TE_MULTILINE | wx.TE_LEFT) + self.status_text_ctrl = wx.TextCtrl( + self.parent_panel, size=(-1, 200), style=wx.TE_MULTILINE | wx.TE_LEFT) self.status_text_ctrl.SetEditable(False) self.status_text_ctrl.SetValue(self.status_log) self.status_gauge = wx.Gauge(self.parent_panel, range=1, size=(-1, -1)) @@ -196,7 +290,8 @@ def __init__(self, parent, title): self.action_button.Disable() self.status_gauge_box_sizer = wx.BoxSizer(wx.HORIZONTAL) - self.status_gauge_box_sizer.Add(self.status_gauge, proportion=1, flag=wx.EXPAND | wx.LEFT | wx.RIGHT, border=5) + self.status_gauge_box_sizer.Add( + self.status_gauge, proportion=1, flag=wx.EXPAND | wx.LEFT | wx.RIGHT, border=5) self.status_gauge_box_sizer.AddSpacer(CHOOSE_SPACER) self.status_gauge_box_sizer.Add(self.action_button, proportion=0, flag=wx.EXPAND | wx.TOP | wx.LEFT | wx.RIGHT, border=2.5) @@ -204,16 +299,22 @@ def __init__(self, parent, title): self.start_conversion_box_sizer.Add(self.status_gauge_box_sizer, proportion=0, flag=wx.EXPAND | wx.ALL, border=5) - self.start_conversion_box_sizer.Add(self.status_text_ctrl, proportion=1, flag=wx.EXPAND | wx.ALL, border=5) + self.start_conversion_box_sizer.Add( + self.status_text_ctrl, proportion=1, flag=wx.EXPAND | wx.ALL, border=5) # build ui self.parent_box_sizer.AddSpacer(15) - self.parent_box_sizer.Add(self.header_box_sizer, proportion=0, flag=wx.EXPAND | wx.RIGHT | wx.LEFT, border=20) + self.parent_box_sizer.Add( + self.header_box_sizer, proportion=0, flag=wx.EXPAND | wx.RIGHT | wx.LEFT, border=20) self.parent_box_sizer.AddSpacer(HEADER_SPACER) - self.parent_box_sizer.Add(self.choose_input_static_box_sizer, proportion=0, flag=wx.EXPAND | wx.ALL, border=5) - self.parent_box_sizer.Add(self.choose_output_static_box_sizer, proportion=0, flag=wx.EXPAND | wx.ALL, border=5) - self.parent_box_sizer.Add(self.set_options_static_box_sizer, proportion=0, flag=wx.EXPAND | wx.ALL, border=5) - self.parent_box_sizer.Add(self.start_conversion_box_sizer, proportion=1, flag=wx.EXPAND | wx.ALL, border=5) + self.parent_box_sizer.Add( + self.choose_input_static_box_sizer, proportion=0, flag=wx.EXPAND | wx.ALL, border=5) + self.parent_box_sizer.Add( + self.choose_output_static_box_sizer, proportion=0, flag=wx.EXPAND | wx.ALL, border=5) + self.parent_box_sizer.Add( + self.set_options_static_box_sizer, proportion=0, flag=wx.EXPAND | wx.ALL, border=5) + self.parent_box_sizer.Add( + self.start_conversion_box_sizer, proportion=1, flag=wx.EXPAND | wx.ALL, border=5) self.parent_panel.SetSizer(self.parent_box_sizer) worker.evt_result(self, self.on_result) @@ -222,6 +323,8 @@ def __init__(self, parent, title): self.Centre() self.Show() + self.check_update_and_show() + @staticmethod def shorten_string(string, max_length): if len(string) >= max_length: @@ -242,9 +345,11 @@ def on_open_file(self, e): dlg.CentreOnParent() if dlg.ShowModal() == wx.ID_OK: self.input_file_path = dlg.GetPath() - self.chosen_file_text.SetLabel(self.shorten_string(self.input_file_path, MAX_PATH_LENGTH)) + self.chosen_file_text.SetLabel(self.shorten_string( + self.input_file_path, MAX_PATH_LENGTH)) self.output_folder_path = ntpath.dirname(self.input_file_path) - self.chosen_folder_text.SetLabel(self.shorten_string(self.output_folder_path, MAX_PATH_LENGTH)) + self.chosen_folder_text.SetLabel(self.shorten_string( + self.output_folder_path, MAX_PATH_LENGTH)) if self.input_file_path and self.output_folder_path: self.action_button.Enable() else: @@ -262,7 +367,8 @@ def on_open_folder(self, e): dlg.CentreOnParent() if dlg.ShowModal() == wx.ID_OK: self.output_folder_path = dlg.GetPath() - self.chosen_folder_text.SetLabel(self.shorten_string(self.output_folder_path, MAX_PATH_LENGTH)) + self.chosen_folder_text.SetLabel(self.shorten_string( + self.output_folder_path, MAX_PATH_LENGTH)) if self.input_file_path and self.output_folder_path: self.action_button.Enable() else: @@ -301,7 +407,8 @@ def on_about(self, e): def on_result(self, event): if event.data is WORKER_FINISH: self.progress_thread.abort() - self.status_text_ctrl.AppendText('-----------------------------------------------------\n\n') + self.status_text_ctrl.AppendText( + '-----------------------------------------------------\n\n') self.action_button.Enable() self.enable_ui(True) self.action_button.SetLabel('Run') @@ -314,6 +421,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): + update_info = UpdateChecker().get_update_information() + + if self.update_window: + self.update_window.Close() + self.update_window = UpdateAvailableFrame(None, update_info) + self.update_window.Centre() + self.update_window.Show() + @staticmethod def is_java_installed(): @@ -334,7 +450,6 @@ def is_java_installed(): return java_version and java_regex.match(java_version) - def enable_ui(self, enable): # Turns UI elements on and off self.choose_file_button.Enable(enable) @@ -348,4 +463,4 @@ def enable_ui(self, enable): app = wx.App() app.SetAppName(TITLE) MainFrame(None, title=TITLE) - app.MainLoop() \ No newline at end of file + app.MainLoop() diff --git a/src/res/update.html b/src/res/update.html new file mode 100644 index 0000000..958cdb4 --- /dev/null +++ b/src/res/update.html @@ -0,0 +1,15 @@ + + + + + + + + +

+ Update @latest_version is available. Click to download.

+ @download_name +

+ + + \ No newline at end of file From a062ccbf5815ed9dc4adb0fb0d380811ed9196c1 Mon Sep 17 00:00:00 2001 From: Khaja Nizamuddin Date: Wed, 31 Jul 2019 21:12:32 +0530 Subject: [PATCH 02/14] timeout added and bg thread done. --- src/main.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main.py b/src/main.py index 9b75bd1..9d81550 100755 --- a/src/main.py +++ b/src/main.py @@ -63,7 +63,7 @@ class UpdateChecker(threading.Thread): def get_update_information(self): - response = requests.get(GITHUB_RELEASES_API) + response = requests.get(GITHUB_RELEASES_API, timeout=30) if response.status_code == 200: json_response = response.json() latest_version = json_response["tag_name"] @@ -323,7 +323,7 @@ def __init__(self, parent, title): self.Centre() self.Show() - self.check_update_and_show() + threading.Thread(target=self.check_update_and_show, args=()).start() @staticmethod def shorten_string(string, max_length): From b320331059d09db6617511ec1d0fcf0aff0d8b14 Mon Sep 17 00:00:00 2001 From: NizamLZ Date: Fri, 2 Aug 2019 22:47:28 +0530 Subject: [PATCH 03/14] update checker works in background --- src/main.py | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/src/main.py b/src/main.py index 9d81550..d325a54 100755 --- a/src/main.py +++ b/src/main.py @@ -59,10 +59,25 @@ 'darwin': 'macos' } +update_checker_event = wx.NewEventType() +on_update_checker_done = wx.PyEventBinder(update_checker_event, 1) + + +class UpdateCheckDoneEvent(wx.PyCommandEvent): + def __init__(self, etype, eid, value=None): + wx.PyCommandEvent.__init__(self, etype, eid) + self.update_info = value + + def GetUpdateInfo(self): + return self.update_info + class UpdateChecker(threading.Thread): + def __init__(self, parent): + threading.Thread.__init__(self) + self._parent = parent - def get_update_information(self): + def run(self): response = requests.get(GITHUB_RELEASES_API, timeout=30) if response.status_code == 200: json_response = response.json() @@ -75,17 +90,18 @@ def get_update_information(self): if OS_MAP[sys.platform] in asset['name'].lower(): download_url = asset['browser_download_url'] download_name = asset['name'] + break - return { + wx.PostEvent(self._parent, UpdateCheckDoneEvent(update_checker_event, -1, { 'update_available': True, 'latest_version': latest_version, 'download_url': download_url, 'download_name': download_name - } + })) else: - return { + wx.PostEvent(self._parent, UpdateCheckDoneEvent(update_checker_event, -1, { 'update_available': False - } + })) class UpdateAvailableFrame(wx.Frame): @@ -323,7 +339,8 @@ def __init__(self, parent, title): self.Centre() self.Show() - threading.Thread(target=self.check_update_and_show, args=()).start() + self.Bind(on_update_checker_done, self.check_update_and_show) + UpdateChecker(self).start() @staticmethod def shorten_string(string, max_length): @@ -421,12 +438,10 @@ 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): - update_info = UpdateChecker().get_update_information() - + def check_update_and_show(self, event): if self.update_window: self.update_window.Close() - self.update_window = UpdateAvailableFrame(None, update_info) + self.update_window = UpdateAvailableFrame(None, event.GetUpdateInfo()) self.update_window.Centre() self.update_window.Show() From b2b82ad249f5881f8677f77f956c3bf5ebe17cd5 Mon Sep 17 00:00:00 2001 From: NizamLZ Date: Fri, 2 Aug 2019 23:05:38 +0530 Subject: [PATCH 04/14] update checker moved to another file --- src/main.py | 38 ++++++++----------------- src/update_checker.py | 66 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 77 insertions(+), 27 deletions(-) create mode 100644 src/update_checker.py diff --git a/src/main.py b/src/main.py index d325a54..dd0a068 100755 --- a/src/main.py +++ b/src/main.py @@ -17,7 +17,6 @@ # TODO pull out all strings # TODO why is the first button selected - TITLE = 'ODK XLSForm Offline' TITLE = 'ODK XLSForm Offline ' + VERSION GITHUB_RELEASES_API = "https://api.github.com/repos/opendatakit/xlsform-offline/releases/latest" @@ -59,26 +58,11 @@ 'darwin': 'macos' } -update_checker_event = wx.NewEventType() -on_update_checker_done = wx.PyEventBinder(update_checker_event, 1) - - -class UpdateCheckDoneEvent(wx.PyCommandEvent): - def __init__(self, etype, eid, value=None): - wx.PyCommandEvent.__init__(self, etype, eid) - self.update_info = value - - def GetUpdateInfo(self): - return self.update_info - class UpdateChecker(threading.Thread): - def __init__(self, parent): - threading.Thread.__init__(self) - self._parent = parent - def run(self): - response = requests.get(GITHUB_RELEASES_API, timeout=30) + def get_update_information(self): + response = requests.get(GITHUB_RELEASES_API) if response.status_code == 200: json_response = response.json() latest_version = json_response["tag_name"] @@ -90,18 +74,17 @@ def run(self): if OS_MAP[sys.platform] in asset['name'].lower(): download_url = asset['browser_download_url'] download_name = asset['name'] - break - wx.PostEvent(self._parent, UpdateCheckDoneEvent(update_checker_event, -1, { + return { 'update_available': True, 'latest_version': latest_version, 'download_url': download_url, 'download_name': download_name - })) + } else: - wx.PostEvent(self._parent, UpdateCheckDoneEvent(update_checker_event, -1, { + return { 'update_available': False - })) + } class UpdateAvailableFrame(wx.Frame): @@ -339,8 +322,7 @@ def __init__(self, parent, title): self.Centre() self.Show() - self.Bind(on_update_checker_done, self.check_update_and_show) - UpdateChecker(self).start() + self.check_update_and_show() @staticmethod def shorten_string(string, max_length): @@ -438,10 +420,12 @@ 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): + def check_update_and_show(self): + update_info = UpdateChecker().get_update_information() + if self.update_window: self.update_window.Close() - self.update_window = UpdateAvailableFrame(None, event.GetUpdateInfo()) + self.update_window = UpdateAvailableFrame(None, update_info) self.update_window.Centre() self.update_window.Show() diff --git a/src/update_checker.py b/src/update_checker.py new file mode 100644 index 0000000..2c022ca --- /dev/null +++ b/src/update_checker.py @@ -0,0 +1,66 @@ +import wx +import sys + +import requests +from packaging import version +import threading + +GITHUB_RELEASES_API = "https://api.github.com/repos/opendatakit/xlsform-offline/releases/latest" + +OS_MAP = { + 'win32': 'windows', + 'darwin': 'macos' +} + +EVT_UPDATE_CHECKER = wx.NewId() + + +def evt_update_check_done(win, func): + '''Define Update Check Done Event.''' + win.Connect(-1, -1, EVT_UPDATE_CHECKER, func) + + +class UpdateCheckDoneEvent(wx.PyEvent): + '''Simple event to check for updates.''' + + def __init__(self, data): + '''Init Update Check Done Event.''' + wx.PyEvent.__init__(self) + self.SetEventType(EVT_UPDATE_CHECKER) + self.data = data + + +class UpdateChecker(threading.Thread): + def __init__(self, parent, current_version): + threading.Thread.__init__(self) + self._parent = parent + self._current_version = current_version + + def run(self): + try: + response = requests.get(GITHUB_RELEASES_API, timeout=30) + if response.status_code == 200: + json_response = response.json() + latest_version = json_response["tag_name"] + print(latest_version) + if version.parse(latest_version[1:]) > version.parse(self._current_version[1:]): + download_url = '' + download_name = '' + for asset in json_response['assets']: + if OS_MAP[sys.platform] in asset['name'].lower(): + download_url = asset['browser_download_url'] + download_name = asset['name'] + break + + wx.PostEvent(self._parent, UpdateCheckDoneEvent({ + 'update_available': True, + 'latest_version': latest_version, + 'download_url': download_url, + 'download_name': download_name + })) + else: + wx.PostEvent(self._parent, UpdateCheckDoneEvent({ + 'update_available': False + })) + except Exception as ex: + pass From 151e21630e7a523bf3461c9de8cd20aefcf2d657 Mon Sep 17 00:00:00 2001 From: NizamLZ Date: Fri, 2 Aug 2019 23:50:20 +0530 Subject: [PATCH 05/14] Show github release desciption as update description --- src/main.py | 10 +++++----- src/res/update.html | 22 +++++++++++++--------- src/update_checker.py | 5 ++++- 3 files changed, 22 insertions(+), 15 deletions(-) diff --git a/src/main.py b/src/main.py index dd0a068..ff56972 100755 --- a/src/main.py +++ b/src/main.py @@ -28,8 +28,8 @@ MAIN_WINDOW_HEIGHT = 620 ABOUT_WINDOW_WIDTH = 360 ABOUT_WINDOW_HEIGHT = 335 -UPDATE_WINDOW_WIDTH = 330 -UPDATE_WINDOW_HEIGHT = 135 +UPDATE_WINDOW_WIDTH = 360 +UPDATE_WINDOW_HEIGHT = 335 MAX_PATH_LENGTH = 45 HEADER_SPACER = 6 CHOOSE_BORDER = 5 @@ -41,8 +41,8 @@ MAIN_WINDOW_HEIGHT = 750 ABOUT_WINDOW_WIDTH = 360 ABOUT_WINDOW_HEIGHT = 290 - UPDATE_WINDOW_WIDTH = 330 - UPDATE_WINDOW_HEIGHT = 100 + UPDATE_WINDOW_WIDTH = 360 + UPDATE_WINDOW_HEIGHT = 290 MAX_PATH_LENGTH = 40 HEADER_SPACER = 0 CHOOSE_BORDER = 1 @@ -104,7 +104,7 @@ def __init__(self, parent, update_info): with open(update_html_path, 'r') as file: update_html_text = file.read() - filled_update_html_text = update_html_text.replace('@latest_version', update_info['latest_version']).replace( + 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) diff --git a/src/res/update.html b/src/res/update.html index 958cdb4..06f7de7 100644 --- a/src/res/update.html +++ b/src/res/update.html @@ -1,15 +1,19 @@ - - - + + + - -

- Update @latest_version is available. Click to download.

- @download_name -

- + +

+ @desc +
+
+
+ Download
+ @download_name +

+ \ No newline at end of file diff --git a/src/update_checker.py b/src/update_checker.py index 2c022ca..bccffd5 100644 --- a/src/update_checker.py +++ b/src/update_checker.py @@ -4,6 +4,7 @@ import requests from packaging import version import threading +import markdown2 GITHUB_RELEASES_API = "https://api.github.com/repos/opendatakit/xlsform-offline/releases/latest" @@ -56,11 +57,13 @@ def run(self): 'update_available': True, 'latest_version': latest_version, 'download_url': download_url, - 'download_name': download_name + 'download_name': download_name, + 'update_desc': markdown2.markdown(json_response["body"].replace('\n', '
')) })) else: wx.PostEvent(self._parent, UpdateCheckDoneEvent({ 'update_available': False })) except Exception as ex: + print ex pass From 6206bd72b01b502ce635ea13414864ba146fa5b5 Mon Sep 17 00:00:00 2001 From: NizamLZ Date: Sat, 3 Aug 2019 14:37:34 +0530 Subject: [PATCH 06/14] Fix line wraps created by the formatter. --- src/main.py | 117 ++++++++++++++++++---------------------------------- 1 file changed, 40 insertions(+), 77 deletions(-) diff --git a/src/main.py b/src/main.py index ff56972..4f6ad0d 100755 --- a/src/main.py +++ b/src/main.py @@ -132,8 +132,7 @@ def OnLinkClicked(self, link): class MainFrame(wx.Frame): def __init__(self, parent, title): super(MainFrame, self).__init__(parent, title=title, - size=(MAIN_WINDOW_WIDTH, - MAIN_WINDOW_HEIGHT), + size=(MAIN_WINDOW_WIDTH, MAIN_WINDOW_HEIGHT), style=wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX) self.input_file_path = u'' self.output_folder_path = u'' @@ -153,10 +152,8 @@ def __init__(self, parent, title): self.file_menu = wx.Menu() self.help_menu = wx.Menu() - 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.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.file_menu.Append(self.quit_menu_item) self.help_menu.Append(self.about_menu_item) @@ -183,26 +180,20 @@ def __init__(self, parent, title): # header self.header_box_sizer = wx.BoxSizer(wx.HORIZONTAL) self.header_box_sizer.AddStretchSpacer() - self.header_box_sizer.Add( - self.about_button, proportion=0, flag=wx.LEFT | wx.RIGHT, border=5) - self.header_box_sizer.Add( - self.quit_button, proportion=0, flag=wx.LEFT | wx.RIGHT, border=5) + self.header_box_sizer.Add(self.about_button, proportion=0, flag=wx.LEFT | wx.RIGHT, border=5) + self.header_box_sizer.Add(self.quit_button, proportion=0, flag=wx.LEFT | wx.RIGHT, border=5) # choose input file self.choose_input_static_box = wx.StaticBox(self.parent_panel, label='1. Choose XLSForm (.xls or .xlsx) for conversion') - self.choose_input_static_box_sizer = wx.StaticBoxSizer( - self.choose_input_static_box, wx.HORIZONTAL) + self.choose_input_static_box_sizer = wx.StaticBoxSizer(self.choose_input_static_box, wx.HORIZONTAL) - self.choose_file_button = wx.Button( - self.parent_panel, label='Choose file...') + self.choose_file_button = wx.Button(self.parent_panel, label='Choose file...') self.choose_file_button.Bind(wx.EVT_BUTTON, self.on_open_file) - self.chosen_file_text = wx.StaticText( - self.parent_panel, label='', size=(-1, -1)) + self.chosen_file_text = wx.StaticText(self.parent_panel, label='', size=(-1, -1)) self.choose_file_box_sizer = wx.BoxSizer(wx.HORIZONTAL) - self.choose_file_box_sizer.Add( - self.choose_file_button, proportion=0, flag=wx.LEFT | wx.RIGHT, border=0) + self.choose_file_box_sizer.Add(self.choose_file_button, proportion=0, flag=wx.LEFT | wx.RIGHT, border=0) self.choose_file_box_sizer.AddSpacer(CHOOSE_SPACER) self.choose_file_box_sizer.Add(self.chosen_file_text, proportion=1, flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.TOP, @@ -213,20 +204,15 @@ def __init__(self, parent, title): # choose output folder self.choose_folder_label = '2. Choose location for output file(s)' - self.choose_output_static_box = wx.StaticBox( - self.parent_panel, label=self.choose_folder_label) - self.choose_output_static_box_sizer = wx.StaticBoxSizer( - self.choose_output_static_box, wx.HORIZONTAL) + self.choose_output_static_box = wx.StaticBox(self.parent_panel, label=self.choose_folder_label) + self.choose_output_static_box_sizer = wx.StaticBoxSizer(self.choose_output_static_box, wx.HORIZONTAL) - self.choose_folder_button = wx.Button( - self.parent_panel, label='Choose location...') + self.choose_folder_button = wx.Button(self.parent_panel, label='Choose location...') self.choose_folder_button.Bind(wx.EVT_BUTTON, self.on_open_folder) - self.chosen_folder_text = wx.StaticText( - self.parent_panel, label='', size=(-1, -1)) + self.chosen_folder_text = wx.StaticText(self.parent_panel, label='', size=(-1, -1)) self.choose_folder_box_sizer = wx.BoxSizer(wx.HORIZONTAL) - self.choose_folder_box_sizer.Add( - self.choose_folder_button, proportion=0, flag=wx.LEFT | wx.RIGHT, border=0) + self.choose_folder_box_sizer.Add(self.choose_folder_button, proportion=0, flag=wx.LEFT | wx.RIGHT, border=0) self.choose_folder_box_sizer.AddSpacer(CHOOSE_SPACER) self.choose_folder_box_sizer.Add(self.chosen_folder_text, proportion=1, flag=wx.EXPAND | wx.LEFT | wx.RIGHT | wx.TOP, @@ -236,50 +222,37 @@ def __init__(self, parent, title): border=5) # set conversion options - self.set_options_static_box = wx.StaticBox( - self.parent_panel, label='3. Set conversion options') - self.set_options_static_box_sizer = wx.StaticBoxSizer( - self.set_options_static_box, wx.VERTICAL) + self.set_options_static_box = wx.StaticBox(self.parent_panel, label='3. Set conversion options') + self.set_options_static_box_sizer = wx.StaticBoxSizer(self.set_options_static_box, wx.VERTICAL) self.overwrite_label = 'Overwrite existing output file(s)' - self.overwrite_checkbox = wx.CheckBox( - self.parent_panel, label=self.overwrite_label, size=(-1, -1)) + self.overwrite_checkbox = wx.CheckBox(self.parent_panel, label=self.overwrite_label, size=(-1, -1)) self.overwrite_checkbox.SetValue(self.overwrite) - self.Bind(wx.EVT_CHECKBOX, self.toggle_overwrite, - id=self.overwrite_checkbox.GetId()) + self.Bind(wx.EVT_CHECKBOX, self.toggle_overwrite, id=self.overwrite_checkbox.GetId()) self.validate_label = 'Validate converted XForm with ODK Validate' if self.is_java_installed(): self.validate = True - self.validate_checkbox = wx.CheckBox( - self.parent_panel, label=self.validate_label, size=(-1, -1)) - self.Bind(wx.EVT_CHECKBOX, self.toggle_validate, - id=self.validate_checkbox.GetId()) + self.validate_checkbox = wx.CheckBox(self.parent_panel, label=self.validate_label, size=(-1, -1)) + self.Bind(wx.EVT_CHECKBOX, self.toggle_validate, id=self.validate_checkbox.GetId()) else: self.validate = False - self.validate_checkbox = wx.CheckBox( - self.parent_panel, label=self.validate_label + ' (Requires Java)') + self.validate_checkbox = wx.CheckBox(self.parent_panel, label=self.validate_label + ' (Requires Java)') self.validate_checkbox.Disable() - self.Bind(wx.EVT_CHECKBOX, self.toggle_validate, - id=self.validate_checkbox.GetId()) + self.Bind(wx.EVT_CHECKBOX, self.toggle_validate, id=self.validate_checkbox.GetId()) self.validate_checkbox.SetValue(self.validate) - self.set_options_static_box_sizer.Add( - self.overwrite_checkbox, flag=wx.LEFT | wx.TOP, border=5) + self.set_options_static_box_sizer.Add(self.overwrite_checkbox, flag=wx.LEFT | wx.TOP, border=5) self.set_options_static_box_sizer.AddStretchSpacer() - self.set_options_static_box_sizer.Add( - self.validate_checkbox, flag=wx.LEFT | wx.TOP, border=5) + self.set_options_static_box_sizer.Add(self.validate_checkbox, flag=wx.LEFT | wx.TOP, border=5) self.set_options_static_box_sizer.AddStretchSpacer() self.set_options_static_box_sizer.AddSpacer(OPTIONS_SPACER) # start conversion - self.start_conversion_static_box = wx.StaticBox( - self.parent_panel, label='4. Run conversion') - self.start_conversion_box_sizer = wx.StaticBoxSizer( - self.start_conversion_static_box, wx.VERTICAL) + self.start_conversion_static_box = wx.StaticBox(self.parent_panel, label='4. Run conversion') + self.start_conversion_box_sizer = wx.StaticBoxSizer(self.start_conversion_static_box, wx.VERTICAL) - self.status_text_ctrl = wx.TextCtrl( - self.parent_panel, size=(-1, 200), style=wx.TE_MULTILINE | wx.TE_LEFT) + self.status_text_ctrl = wx.TextCtrl(self.parent_panel, size=(-1, 200), style=wx.TE_MULTILINE | wx.TE_LEFT) self.status_text_ctrl.SetEditable(False) self.status_text_ctrl.SetValue(self.status_log) self.status_gauge = wx.Gauge(self.parent_panel, range=1, size=(-1, -1)) @@ -289,8 +262,7 @@ def __init__(self, parent, title): self.action_button.Disable() self.status_gauge_box_sizer = wx.BoxSizer(wx.HORIZONTAL) - self.status_gauge_box_sizer.Add( - self.status_gauge, proportion=1, flag=wx.EXPAND | wx.LEFT | wx.RIGHT, border=5) + self.status_gauge_box_sizer.Add(self.status_gauge, proportion=1, flag=wx.EXPAND | wx.LEFT | wx.RIGHT, border=5) self.status_gauge_box_sizer.AddSpacer(CHOOSE_SPACER) self.status_gauge_box_sizer.Add(self.action_button, proportion=0, flag=wx.EXPAND | wx.TOP | wx.LEFT | wx.RIGHT, border=2.5) @@ -298,22 +270,16 @@ def __init__(self, parent, title): self.start_conversion_box_sizer.Add(self.status_gauge_box_sizer, proportion=0, flag=wx.EXPAND | wx.ALL, border=5) - self.start_conversion_box_sizer.Add( - self.status_text_ctrl, proportion=1, flag=wx.EXPAND | wx.ALL, border=5) + self.start_conversion_box_sizer.Add(self.status_text_ctrl, proportion=1, flag=wx.EXPAND | wx.ALL, border=5) # build ui self.parent_box_sizer.AddSpacer(15) - self.parent_box_sizer.Add( - self.header_box_sizer, proportion=0, flag=wx.EXPAND | wx.RIGHT | wx.LEFT, border=20) + self.parent_box_sizer.Add(self.header_box_sizer, proportion=0, flag=wx.EXPAND | wx.RIGHT | wx.LEFT, border=20) self.parent_box_sizer.AddSpacer(HEADER_SPACER) - self.parent_box_sizer.Add( - self.choose_input_static_box_sizer, proportion=0, flag=wx.EXPAND | wx.ALL, border=5) - self.parent_box_sizer.Add( - self.choose_output_static_box_sizer, proportion=0, flag=wx.EXPAND | wx.ALL, border=5) - self.parent_box_sizer.Add( - self.set_options_static_box_sizer, proportion=0, flag=wx.EXPAND | wx.ALL, border=5) - self.parent_box_sizer.Add( - self.start_conversion_box_sizer, proportion=1, flag=wx.EXPAND | wx.ALL, border=5) + self.parent_box_sizer.Add(self.choose_input_static_box_sizer, proportion=0, flag=wx.EXPAND | wx.ALL, border=5) + self.parent_box_sizer.Add(self.choose_output_static_box_sizer, proportion=0, flag=wx.EXPAND | wx.ALL, border=5) + self.parent_box_sizer.Add(self.set_options_static_box_sizer, proportion=0, flag=wx.EXPAND | wx.ALL, border=5) + self.parent_box_sizer.Add(self.start_conversion_box_sizer, proportion=1, flag=wx.EXPAND | wx.ALL, border=5) self.parent_panel.SetSizer(self.parent_box_sizer) worker.evt_result(self, self.on_result) @@ -322,7 +288,8 @@ def __init__(self, parent, title): self.Centre() self.Show() - self.check_update_and_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): @@ -344,11 +311,9 @@ def on_open_file(self, e): dlg.CentreOnParent() if dlg.ShowModal() == wx.ID_OK: self.input_file_path = dlg.GetPath() - self.chosen_file_text.SetLabel(self.shorten_string( - self.input_file_path, MAX_PATH_LENGTH)) + self.chosen_file_text.SetLabel(self.shorten_string(self.input_file_path, MAX_PATH_LENGTH)) self.output_folder_path = ntpath.dirname(self.input_file_path) - self.chosen_folder_text.SetLabel(self.shorten_string( - self.output_folder_path, MAX_PATH_LENGTH)) + self.chosen_folder_text.SetLabel(self.shorten_string(self.output_folder_path, MAX_PATH_LENGTH)) if self.input_file_path and self.output_folder_path: self.action_button.Enable() else: @@ -366,8 +331,7 @@ def on_open_folder(self, e): dlg.CentreOnParent() if dlg.ShowModal() == wx.ID_OK: self.output_folder_path = dlg.GetPath() - self.chosen_folder_text.SetLabel(self.shorten_string( - self.output_folder_path, MAX_PATH_LENGTH)) + self.chosen_folder_text.SetLabel(self.shorten_string(self.output_folder_path, MAX_PATH_LENGTH)) if self.input_file_path and self.output_folder_path: self.action_button.Enable() else: @@ -406,8 +370,7 @@ def on_about(self, e): def on_result(self, event): if event.data is WORKER_FINISH: self.progress_thread.abort() - self.status_text_ctrl.AppendText( - '-----------------------------------------------------\n\n') + self.status_text_ctrl.AppendText('-----------------------------------------------------\n\n') self.action_button.Enable() self.enable_ui(True) self.action_button.SetLabel('Run') From 5fdcc2a61ca8a8647b5eec3e7fb30f00f1eade81 Mon Sep 17 00:00:00 2001 From: NizamLZ Date: Sat, 3 Aug 2019 14:44:15 +0530 Subject: [PATCH 07/14] remove print statement --- src/update_checker.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/update_checker.py b/src/update_checker.py index bccffd5..da06feb 100644 --- a/src/update_checker.py +++ b/src/update_checker.py @@ -43,7 +43,6 @@ def run(self): if response.status_code == 200: json_response = response.json() latest_version = json_response["tag_name"] - print(latest_version) if version.parse(latest_version[1:]) > version.parse(self._current_version[1:]): download_url = '' download_name = '' From 6b01e96c4b41a805e74ffe95acf145f909705f01 Mon Sep 17 00:00:00 2001 From: Mitchell Estberg Date: Fri, 10 Jan 2020 13:12:10 -0800 Subject: [PATCH 08/14] Lightweight version of update checker --- src/main.py | 16 ++++++++-------- src/res/update.html | 2 +- src/update_checker.py | 24 ++++++++++++++++-------- 3 files changed, 25 insertions(+), 17 deletions(-) diff --git a/src/main.py b/src/main.py index 4f6ad0d..29471fe 100755 --- a/src/main.py +++ b/src/main.py @@ -11,14 +11,11 @@ import wx import worker -import requests -from packaging import version -import threading +import update_checker # TODO pull out all strings # TODO why is the first button selected TITLE = 'ODK XLSForm Offline' -TITLE = 'ODK XLSForm Offline ' + VERSION GITHUB_RELEASES_API = "https://api.github.com/repos/opendatakit/xlsform-offline/releases/latest" APP_QUIT = 1 @@ -53,6 +50,7 @@ WORKER_PROGRESS = 'WORKER_PROGRESS' WORKER_PROGRESS_SLEEP = .05 +<<<<<<< HEAD OS_MAP = { 'win32': 'windows', 'darwin': 'macos' @@ -87,6 +85,8 @@ def get_update_information(self): } +======= +>>>>>>> Lightweight version of update checker 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', @@ -109,7 +109,6 @@ def __init__(self, parent, update_info): html.SetPage(filled_update_html_text) - class AboutFrame(wx.Frame): def __init__(self, parent): wx.Frame.__init__(self, parent, wx.ID_ANY, title='About ' + TITLE, @@ -117,7 +116,7 @@ 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 = os.path.join('res','about.html') if getattr(sys, 'frozen', False): html.LoadPage(os.path.join(sys._MEIPASS, about)) else: @@ -146,7 +145,6 @@ def __init__(self, parent, title): self.progress_thread = None self.about_window = None - self.update_window = None self.menu_bar = wx.MenuBar() self.file_menu = wx.Menu() @@ -154,6 +152,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) @@ -412,6 +411,7 @@ def is_java_installed(): return java_version and java_regex.match(java_version) + def enable_ui(self, enable): # Turns UI elements on and off self.choose_file_button.Enable(enable) @@ -425,4 +425,4 @@ def enable_ui(self, enable): app = wx.App() app.SetAppName(TITLE) MainFrame(None, title=TITLE) - app.MainLoop() + app.MainLoop() \ No newline at end of file diff --git a/src/res/update.html b/src/res/update.html index 06f7de7..7fb0e6f 100644 --- a/src/res/update.html +++ b/src/res/update.html @@ -16,4 +16,4 @@

- \ No newline at end of file + \ No newline at end of file diff --git a/src/update_checker.py b/src/update_checker.py index da06feb..827d61b 100644 --- a/src/update_checker.py +++ b/src/update_checker.py @@ -1,12 +1,13 @@ import wx import sys -import requests from packaging import version import threading -import markdown2 +import json +import urllib2 GITHUB_RELEASES_API = "https://api.github.com/repos/opendatakit/xlsform-offline/releases/latest" +GITHUB_MARKDOWN_API = "https://api.github.com/markdown/raw" OS_MAP = { 'win32': 'windows', @@ -39,9 +40,9 @@ def __init__(self, parent, current_version): def run(self): try: - response = requests.get(GITHUB_RELEASES_API, timeout=30) - if response.status_code == 200: - json_response = response.json() + response = urllib2.urlopen(GITHUB_RELEASES_API) + if response.getcode() == 200: + json_response = json.load(response) latest_version = json_response["tag_name"] if version.parse(latest_version[1:]) > version.parse(self._current_version[1:]): download_url = '' @@ -52,17 +53,24 @@ def run(self): download_name = asset['name'] break + # second request is for markdown conversion + data = json_response["body"] + request = urllib2.Request(url=GITHUB_MARKDOWN_API, headers={'Content-Type': 'text/plain'}, data=data) + res = urllib2.urlopen(request) + html_body = res.read() + wx.PostEvent(self._parent, UpdateCheckDoneEvent({ 'update_available': True, 'latest_version': latest_version, 'download_url': download_url, 'download_name': download_name, - 'update_desc': markdown2.markdown(json_response["body"].replace('\n', '
')) + 'update_desc': html_body })) else: wx.PostEvent(self._parent, UpdateCheckDoneEvent({ 'update_available': False })) except Exception as ex: - print ex - pass + print("EXCEPTION") + print(ex) + pass \ No newline at end of file From 584d704494953c0c87cc81a3daddc91d8202ac1c Mon Sep 17 00:00:00 2001 From: Mitchell Estberg Date: Fri, 10 Jan 2020 13:24:30 -0800 Subject: [PATCH 09/14] Clearer Update Message --- src/res/update.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/res/update.html b/src/res/update.html index 7fb0e6f..dc09467 100644 --- a/src/res/update.html +++ b/src/res/update.html @@ -11,9 +11,9 @@


- Download
+ Download New Version
@download_name

- \ No newline at end of file + \ No newline at end of file From e33050de7936607c7ef82b161d2dc3820852f2bd Mon Sep 17 00:00:00 2001 From: Mitchell Estberg Date: Fri, 10 Jan 2020 14:10:34 -0800 Subject: [PATCH 10/14] Weird merge issues resolved. --- src/main.py | 60 ++++++++++++----------------------------------------- 1 file changed, 13 insertions(+), 47 deletions(-) diff --git a/src/main.py b/src/main.py index 29471fe..072c581 100755 --- a/src/main.py +++ b/src/main.py @@ -16,6 +16,7 @@ # TODO pull out all strings # TODO why is the first button selected TITLE = 'ODK XLSForm Offline' + GITHUB_RELEASES_API = "https://api.github.com/repos/opendatakit/xlsform-offline/releases/latest" APP_QUIT = 1 @@ -24,9 +25,9 @@ MAIN_WINDOW_WIDTH = 475 MAIN_WINDOW_HEIGHT = 620 ABOUT_WINDOW_WIDTH = 360 -ABOUT_WINDOW_HEIGHT = 335 +ABOUT_WINDOW_HEIGHT = 365 UPDATE_WINDOW_WIDTH = 360 -UPDATE_WINDOW_HEIGHT = 335 +UPDATE_WINDOW_HEIGHT = 365 MAX_PATH_LENGTH = 45 HEADER_SPACER = 6 CHOOSE_BORDER = 5 @@ -37,9 +38,9 @@ MAIN_WINDOW_WIDTH = 500 MAIN_WINDOW_HEIGHT = 750 ABOUT_WINDOW_WIDTH = 360 - ABOUT_WINDOW_HEIGHT = 290 + ABOUT_WINDOW_HEIGHT = 315 UPDATE_WINDOW_WIDTH = 360 - UPDATE_WINDOW_HEIGHT = 290 + UPDATE_WINDOW_HEIGHT = 315 MAX_PATH_LENGTH = 40 HEADER_SPACER = 0 CHOOSE_BORDER = 1 @@ -50,43 +51,6 @@ WORKER_PROGRESS = 'WORKER_PROGRESS' WORKER_PROGRESS_SLEEP = .05 -<<<<<<< HEAD -OS_MAP = { - 'win32': 'windows', - 'darwin': 'macos' -} - - -class UpdateChecker(threading.Thread): - - def get_update_information(self): - response = requests.get(GITHUB_RELEASES_API) - if response.status_code == 200: - json_response = response.json() - latest_version = json_response["tag_name"] - print(latest_version) - if version.parse(latest_version[1:]) > version.parse(VERSION[1:]): - download_url = '' - download_name = '' - for asset in json_response['assets']: - if OS_MAP[sys.platform] in asset['name'].lower(): - download_url = asset['browser_download_url'] - download_name = asset['name'] - - return { - 'update_available': True, - 'latest_version': latest_version, - 'download_url': download_url, - 'download_name': download_name - } - else: - return { - 'update_available': False - } - - -======= ->>>>>>> Lightweight version of update checker 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', @@ -358,6 +322,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: @@ -382,14 +348,14 @@ 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): - update_info = UpdateChecker().get_update_information() - + def check_update_and_show(self, event): if self.update_window: self.update_window.Close() - self.update_window = UpdateAvailableFrame(None, update_info) - self.update_window.Centre() - self.update_window.Show() + + 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(): From 8a823717cbb58ae5b0c1bc81bd2adf800706799a Mon Sep 17 00:00:00 2001 From: Mitchell Estberg Date: Fri, 1 May 2020 12:31:03 -0700 Subject: [PATCH 11/14] Fixing updates required for python 3 --- requirements.txt | 1 - src/main.py | 18 ++++++++++++++---- src/res/about.html | 2 +- src/update_checker.py | 16 ++++++++-------- 4 files changed, 23 insertions(+), 14 deletions(-) diff --git a/requirements.txt b/requirements.txt index 35fd5d9..35f1a75 100644 --- a/requirements.txt +++ b/requirements.txt @@ -3,4 +3,3 @@ pyinstaller wxpython pyxform -packaging diff --git a/src/main.py b/src/main.py index 072c581..4589de1 100755 --- a/src/main.py +++ b/src/main.py @@ -17,7 +17,7 @@ # TODO why is the first button selected TITLE = 'ODK XLSForm Offline' -GITHUB_RELEASES_API = "https://api.github.com/repos/opendatakit/xlsform-offline/releases/latest" +VERSION = "2.0.0" APP_QUIT = 1 APP_ABOUT = 2 @@ -80,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): @@ -252,6 +261,7 @@ def __init__(self, parent, title): self.Show() update_checker.evt_update_check_done(self, self.check_update_and_show) + print("CHECKING FOR UPDATE") update_checker.UpdateChecker(self, VERSION).start() @staticmethod diff --git a/src/res/about.html b/src/res/about.html index c9fa879..b84480b 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!

- v2.0.0 + v@version

\ No newline at end of file diff --git a/src/update_checker.py b/src/update_checker.py index 827d61b..16f9b40 100644 --- a/src/update_checker.py +++ b/src/update_checker.py @@ -1,10 +1,9 @@ import wx import sys -from packaging import version import threading import json -import urllib2 +import urllib GITHUB_RELEASES_API = "https://api.github.com/repos/opendatakit/xlsform-offline/releases/latest" GITHUB_MARKDOWN_API = "https://api.github.com/markdown/raw" @@ -40,11 +39,11 @@ def __init__(self, parent, current_version): def run(self): try: - response = urllib2.urlopen(GITHUB_RELEASES_API) + response = urllib.request.urlopen(GITHUB_RELEASES_API) if response.getcode() == 200: json_response = json.load(response) latest_version = json_response["tag_name"] - if version.parse(latest_version[1:]) > version.parse(self._current_version[1:]): + if latest_version[1:] > self._current_version: download_url = '' download_name = '' for asset in json_response['assets']: @@ -54,10 +53,11 @@ def run(self): break # second request is for markdown conversion - data = json_response["body"] - request = urllib2.Request(url=GITHUB_MARKDOWN_API, headers={'Content-Type': 'text/plain'}, data=data) - res = urllib2.urlopen(request) - html_body = res.read() + data = json_response["body"].encode('utf-8') + headers = {'Content-Type': 'text/plain'} + + request = urllib.request.Request(url=GITHUB_MARKDOWN_API, data=data, headers=headers) + html_body = urllib.request.urlopen(request).read().decode('utf-8') wx.PostEvent(self._parent, UpdateCheckDoneEvent({ 'update_available': True, From 9a127f22fd066aa360ac0c2d545930312e67d2de Mon Sep 17 00:00:00 2001 From: Mitchell Estberg Date: Fri, 1 May 2020 12:35:36 -0700 Subject: [PATCH 12/14] Reflect rebranding --- src/main.py | 1 - src/res/about.html | 2 +- src/update_checker.py | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main.py b/src/main.py index 4589de1..af62d69 100755 --- a/src/main.py +++ b/src/main.py @@ -261,7 +261,6 @@ def __init__(self, parent, title): self.Show() update_checker.evt_update_check_done(self, self.check_update_and_show) - print("CHECKING FOR UPDATE") update_checker.UpdateChecker(self, VERSION).start() @staticmethod diff --git a/src/res/about.html b/src/res/about.html index b84480b..838f38f 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!

- v@version + v@version

\ No newline at end of file diff --git a/src/update_checker.py b/src/update_checker.py index 16f9b40..cdd2a7b 100644 --- a/src/update_checker.py +++ b/src/update_checker.py @@ -5,7 +5,7 @@ import json import urllib -GITHUB_RELEASES_API = "https://api.github.com/repos/opendatakit/xlsform-offline/releases/latest" +GITHUB_RELEASES_API = "https://api.github.com/repos/getodk/xlsform-offline/releases/latest" GITHUB_MARKDOWN_API = "https://api.github.com/markdown/raw" OS_MAP = { From d6cec71ac0214d5793da7807f2cf520345f02ac9 Mon Sep 17 00:00:00 2001 From: Mitchell Estberg Date: Fri, 1 May 2020 12:39:08 -0700 Subject: [PATCH 13/14] Now new line in requirements.txt --- requirements.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 35f1a75..c843ff5 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,4 @@ # macOS: Use the default Python. virtualenvs will not work. - pyinstaller wxpython pyxform From 4f2e14ff39ae097cffc8e1f7b248c090d68ff0eb Mon Sep 17 00:00:00 2001 From: Mitchell Estberg Date: Mon, 4 May 2020 17:53:05 -0700 Subject: [PATCH 14/14] Update to make on Windows work. Co-authored-by: Pieter Benjamin --- pkg/xlsform-offline-win.spec | 1 + 1 file changed, 1 insertion(+) 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',