Skip to content
This repository was archived by the owner on Apr 30, 2021. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions pkg/xlsform-offline-win.spec
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
60 changes: 56 additions & 4 deletions src/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,23 @@
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

MAIN_WINDOW_WIDTH = 475
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
Expand All @@ -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
Expand All @@ -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):
Expand All @@ -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):
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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:
Expand All @@ -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():

Expand Down
2 changes: 1 addition & 1 deletion src/res/about.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<b>ODK is a community-powered project and the community lives on the <a href="https://forum.getodk.org">ODK Forum</a>. Join the forum to get support, request features, meet other ODKers, and contribute to the project!</b>
</p>
<p align="center"><u><small>
<a href="https://github.com/getodk/xlsform-offline/releases/tag/v2.0.0">v2.0.0</a></small></u>
<a href="https://github.com/getodk/xlsform-offline/releases/tag/v@version">v@version</a></small></u>
</p>
</body>
</html>
19 changes: 19 additions & 0 deletions src/res/update.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN">
<html>

<head>
<title></title>
</head>

<body>
<p>
@desc
<br />
<br />
<br />
<b>Download New Version</b><br />
<a href="@download_url">@download_name</a>
</p>
</body>

</html>
76 changes: 76 additions & 0 deletions src/update_checker.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import wx
import sys

import threading
import json
import urllib

GITHUB_RELEASES_API = "https://api.github.com/repos/getodk/xlsform-offline/releases/latest"
GITHUB_MARKDOWN_API = "https://api.github.com/markdown/raw"

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 = urllib.request.urlopen(GITHUB_RELEASES_API)
if response.getcode() == 200:
json_response = json.load(response)
latest_version = json_response["tag_name"]
if latest_version[1:] > self._current_version:
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

# second request is for markdown conversion
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,
'latest_version': latest_version,
'download_url': download_url,
'download_name': download_name,
'update_desc': html_body
}))
else:
wx.PostEvent(self._parent, UpdateCheckDoneEvent({
'update_available': False
}))
except Exception as ex:
print("EXCEPTION")
print(ex)
pass