[959eb01] | 1 | """ |
---|
| 2 | documentation module provides a simple means to add help throughout the |
---|
| 3 | application. It checks for the existence of html2 package needed to support |
---|
[914ba0a] | 4 | fully html panel which supports css. The class defined here takes a title for |
---|
| 5 | the particular help panel, a pointer to the html documentation file of interest |
---|
| 6 | within the documentation tree along with a 'command' string such as a page |
---|
| 7 | anchor or a query string etc. The path to the doc directory is retrieved |
---|
| 8 | automatically by the class itself. Thus with these three pieces of information |
---|
| 9 | the class generates a panel with the appropriate title bar and help file |
---|
| 10 | formatted according the style sheets called in the html file. Finally, if an |
---|
| 11 | old version of Python is running and the html2 package is not available the |
---|
| 12 | class brings up the default browser and passes the file:/// string to it. In |
---|
| 13 | this case however the instruction portion is usually not passed for security |
---|
| 14 | reasons. |
---|
| 15 | """ |
---|
| 16 | import os |
---|
| 17 | import logging |
---|
| 18 | import webbrowser |
---|
| 19 | import urllib |
---|
| 20 | import sys |
---|
| 21 | |
---|
| 22 | import wx |
---|
| 23 | try: |
---|
| 24 | import wx.html2 as html |
---|
| 25 | WX_SUPPORTS_HTML2 = True |
---|
[9d566b2] | 26 | except ImportError: |
---|
[914ba0a] | 27 | WX_SUPPORTS_HTML2 = False |
---|
[959eb01] | 28 | |
---|
[914ba0a] | 29 | from sas.sasgui import get_app_dir |
---|
| 30 | |
---|
[2746eab] | 31 | # Don't use wx html renderer on windows. |
---|
| 32 | if os.name == 'nt': |
---|
| 33 | WX_SUPPORTS_HTML2 = False |
---|
| 34 | |
---|
[914ba0a] | 35 | logger = logging.getLogger(__name__) |
---|
| 36 | |
---|
| 37 | SPHINX_DOC_ENV = "SASVIEW_DOC_PATH" |
---|
[959eb01] | 38 | |
---|
[9d566b2] | 39 | THREAD_STARTED = False |
---|
| 40 | def start_documentation_server(doc_root, port): |
---|
| 41 | import thread |
---|
| 42 | global THREAD_STARTED |
---|
| 43 | if not THREAD_STARTED: |
---|
| 44 | thread.start_new_thread(_documentation_server, (doc_root, port)) |
---|
| 45 | THREAD_STARTED = True |
---|
[959eb01] | 46 | |
---|
[9d566b2] | 47 | def _documentation_server(doc_root, port): |
---|
| 48 | from SimpleHTTPServer import SimpleHTTPRequestHandler |
---|
| 49 | from SocketServer import TCPServer |
---|
[959eb01] | 50 | |
---|
[9d566b2] | 51 | os.chdir(doc_root) |
---|
| 52 | httpd = TCPServer(("127.0.0.1", port), SimpleHTTPRequestHandler, bind_and_activate=False) |
---|
| 53 | httpd.allow_reuse_address = True |
---|
| 54 | try: |
---|
| 55 | httpd.server_bind() |
---|
| 56 | httpd.server_activate() |
---|
| 57 | httpd.serve_forever() |
---|
| 58 | finally: |
---|
| 59 | httpd.server_close() |
---|
[959eb01] | 60 | |
---|
| 61 | class DocumentationWindow(wx.Frame): |
---|
| 62 | """ |
---|
| 63 | DocumentationWindow inherits from wx.Frame and provides a centralized |
---|
| 64 | coherent framework for all help documentation. Help files must be html |
---|
| 65 | files stored in an properly organized tree below the top 'doc' folder. In |
---|
| 66 | order to display the appropriate help file from anywhere in the gui, the |
---|
| 67 | code simply needs to know the location below the top level where the |
---|
| 68 | help file resides along with the name of the help file. |
---|
| 69 | called |
---|
| 70 | (self, parent, dummy_id, path, url_instruction, title, size=(850, 540)) |
---|
| 71 | |
---|
| 72 | :param path: path to html file beginning AFTER /doc/ and ending in the\ |
---|
| 73 | file.html. |
---|
| 74 | :param url_instructions: anchor string or other query e.g. '#MyAnchor' |
---|
| 75 | :param title: text to place in the title bar of the help panel |
---|
| 76 | """ |
---|
| 77 | def __init__(self, parent, dummy_id, path, url_instruction, title, size=(850, 540)): |
---|
| 78 | wx.Frame.__init__(self, parent, dummy_id, title, size=size) |
---|
| 79 | |
---|
| 80 | if SPHINX_DOC_ENV in os.environ: |
---|
| 81 | docs_path = os.path.join(os.environ[SPHINX_DOC_ENV]) |
---|
| 82 | else: |
---|
| 83 | # For the installer, docs are in a top-level directory. We're not |
---|
| 84 | # bothering to worry about docs when running using the old |
---|
| 85 | # (non - run.py) way. |
---|
| 86 | docs_path = os.path.join(get_app_dir(), "doc") |
---|
| 87 | |
---|
| 88 | #note that filepath for mac OS, at least in bundle starts with a |
---|
| 89 | #forward slash as /Application, while the PC string begins C:\ |
---|
| 90 | #It seems that mac OS is happy with four slashes as in file:////App... |
---|
| 91 | #Two slashes is not sufficient to indicate path from root. Thus for now |
---|
| 92 | #we use "file:///" +... If the mac behavior changes may need to make the |
---|
| 93 | #file:/// be another constant at the beginning that yields // for Mac |
---|
| 94 | #and /// for PC. |
---|
| 95 | #Note added June 21, 2015 PDB |
---|
| 96 | file_path = os.path.join(docs_path, path) |
---|
[9d566b2] | 97 | if path.startswith('http'): |
---|
| 98 | url = path |
---|
| 99 | elif not os.path.exists(file_path): |
---|
| 100 | url = "index.html" |
---|
[f80b416e] | 101 | logger.error("Could not find Sphinx documentation at %s -- has it been built?", |
---|
| 102 | file_path) |
---|
[35ddae5] | 103 | elif False: |
---|
[9d566b2] | 104 | start_documentation_server(docs_path, port=7999) |
---|
[35ddae5] | 105 | url = "http://127.0.0.1:7999/" + path.replace('\\', '/') + url_instruction |
---|
[9d566b2] | 106 | else: |
---|
| 107 | url = "file:///" + urllib.quote(file_path, r'/\:')+ url_instruction |
---|
[959eb01] | 108 | |
---|
[f80b416e] | 109 | #logger.info("showing url " + url) |
---|
[9d566b2] | 110 | if WX_SUPPORTS_HTML2: |
---|
[959eb01] | 111 | # Complete HTML/CSS support! |
---|
| 112 | self.view = html.WebView.New(self) |
---|
| 113 | self.view.LoadURL(url) |
---|
[9d566b2] | 114 | self.Bind(html.EVT_WEBVIEW_ERROR, self.OnError, self.view) |
---|
[959eb01] | 115 | self.Show() |
---|
| 116 | else: |
---|
| 117 | logger.error("No html2 support, popping up a web browser") |
---|
| 118 | #For cases that do not build against current version dependency |
---|
| 119 | # Wx 3.0 we provide a webbrowser call - this is particularly for |
---|
| 120 | #Red hat used at SNS for which Wx 3.0 is not available. This |
---|
| 121 | #does not deal with issue of math in docs of course. |
---|
| 122 | webbrowser.open_new_tab(url) |
---|
| 123 | |
---|
[9d566b2] | 124 | def OnError(self, evt): |
---|
| 125 | logger.error("%d: %s", evt.GetInt(), evt.GetString()) |
---|
| 126 | |
---|
[959eb01] | 127 | def main(): |
---|
| 128 | """ |
---|
| 129 | main loop function if running alone for testing. |
---|
| 130 | """ |
---|
[9d566b2] | 131 | url = "index.html" if len(sys.argv) <= 1 else sys.argv[1] |
---|
[959eb01] | 132 | app = wx.App() |
---|
[9d566b2] | 133 | DocumentationWindow(None, -1, url, "", "Documentation",) |
---|
[959eb01] | 134 | app.MainLoop() |
---|
| 135 | |
---|
| 136 | if __name__ == '__main__': |
---|
| 137 | main() |
---|