def main(): print 'Starting Central Access Reader...' import sys import os from PyQt4.QtGui import QApplication, QPixmap, QSplashScreen app = QApplication(sys.argv) # Create a splash screen from forms import resource_rc pixmap = QPixmap(':/icons/icons/CAR Splash.png') splash = QSplashScreen(pixmap) splash.show() app.processEvents() # Check to see if my folders in my paths exist. If they don't, make them from misc import program_path, app_data_path, temp_path if not os.path.exists(os.path.dirname(program_path('test.txt'))): os.makedirs(os.path.dirname(program_path('test.txt'))) if not os.path.exists(os.path.dirname(app_data_path('test.txt'))): os.makedirs(os.path.dirname(app_data_path('test.txt'))) if not os.path.exists(os.path.dirname(temp_path('test.txt'))): os.makedirs(os.path.dirname(temp_path('test.txt'))) from gui.main_window import MainWindow window = MainWindow(app) window.show() splash.finish(window) sys.exit(app.exec_())
def _prepareHead(self, head, mathOutput='html'): mathjaxConfig = HTML.Element('script') mathjaxConfig.set('type', 'text/x-mathjax-config') mathjaxConfigFile = '' if mathOutput == 'svg': mathjaxConfigFile = program_path('src/javascript/mathjax_config_svg.jsconfig') else: mathjaxConfigFile = program_path('src/javascript/mathjax_config.jsconfig') scriptFile = open(mathjaxConfigFile, 'r') contents = scriptFile.read() scriptFile.close() mathjaxConfig.text = contents mathjaxScript = HTML.Element('script') mathjaxScript.attrib['type'] = 'text/javascript' mathjaxScript.attrib['src'] = 'file:' + urllib.pathname2url(program_path('mathjax/MathJax.js')) jqueryScript = HTML.Element('script') jqueryScript.attrib['type'] = 'text/javascript' jqueryScript.attrib['src'] = 'file:' + urllib.pathname2url(program_path('jquery-1.9.1.min.js')) jqueryUIScript = HTML.Element('script') jqueryUIScript.attrib['type'] = 'text/javascript' jqueryUIScript.attrib['src'] = 'file:' + urllib.pathname2url(program_path('jquery-ui/js/jquery-ui-1.9.2.custom.js')) jqueryScrollTo = HTML.Element('script') jqueryScrollTo.attrib['type'] = 'text/javascript' jqueryScrollTo.attrib['src'] = 'file:' + urllib.pathname2url(program_path('jquery.scrollTo-1.4.3.1-min.js')) # Get all of my own JavaScripts into the document javascriptFiles = [f for f in os.listdir(program_path('src/javascript/')) if os.path.isfile(os.path.join(program_path('src/javascript/'), f)) and os.path.splitext(os.path.join(program_path('src/javascript/'), f))[1] == '.js'] javascriptElements = [] for f in javascriptFiles: elem = HTML.Element('script') elem.set('language', 'javascript') elem.set('type', 'text/javascript') with open(os.path.join(program_path('src/javascript/'), f), 'r') as jsFile: elem.text = jsFile.read() javascriptElements.append(elem) css = HTML.Element('link') css.attrib['rel'] = 'stylesheet' css.attrib['type'] = 'text/css' css.attrib['href'] = 'file:' + urllib.pathname2url(temp_path('import/defaultStyle.css')) head.append(mathjaxConfig) head.append(mathjaxScript) head.append(jqueryScript) head.append(jqueryUIScript) head.append(jqueryScrollTo) for elem in javascriptElements: head.append(elem) head.append(css)
def start(self): ''' Starts the conversion process. ''' def myLoadProgress(progress): self._loadProgress = progress def myLoadFinished(isLoaded): self._loaded = True webpage = QWebPage() webpage.loadProgress.connect(myLoadProgress) webpage.loadFinished.connect(myLoadFinished) url = misc.temp_path('import') baseUrl = QUrl.fromLocalFile(url) webpage.mainFrame().setHtml( self._document.getMainPage(mathOutput='svg'), baseUrl) while not self._loaded and not self._canceled: qApp.processEvents() self.ui.label.setText('Typesetting math equations...') if not self._canceled: # Wait for the MathJax to typeset while not self._mathTypeset and not self._canceled: qApp.processEvents() progress = int(webpage.mainFrame().evaluateJavaScript( misc.js_command('GetMathTypesetProgress', [])).toInt()[0]) self.ui.progressBar.setValue(progress) self._mathTypeset = webpage.mainFrame().evaluateJavaScript( misc.js_command('IsMathTypeset', [])).toBool() # If I haven't canceled yet, let's convert the document in a # separate thread if not self._canceled: self._thread = ExportToHtmlThread( unicode(webpage.mainFrame().evaluateJavaScript( misc.js_command('GetBodyHTML', [])).toString()), self._configuration, self._assigner, self._filePath) self._thread.onProgress.connect(self.ui.progressBar.setValue) self._thread.onProgressLabel.connect(self.ui.label.setText) self._thread.finished.connect(self._threadFinished) self.ui.cancelButton.clicked.connect(self._thread.quit) self._thread.start()
def __init__(self, docxFilePath, progressHook=None, cancelHook=None): ''' Generates the document structure from the .docx file. ''' self.importFolder = temp_path('import') if progressHook is not None: progressHook(0) print 'Cleaning up things...' # Delete all of the images in my import directory, if any if os.path.isdir(self.importFolder + '/images'): for the_file in os.listdir(self.importFolder + '/images'): file_path = os.path.join(self.importFolder + '/images', the_file) try: if os.path.isfile(file_path): os.unlink(file_path) except Exception, e: print e
def __init__(self, mathml): super(MathMLItem, self).__init__() self.layout = QtGui.QHBoxLayout(self) # Generate the correct HTML code to display the MathML root = etree.Element('html') head = etree.SubElement(root, 'head') body = etree.SubElement(root, 'body') mathjaxScript = etree.Element('script') mathjaxScript.attrib['type'] = 'text/javascript' mathjaxScript.attrib['src'] = 'file:' + urllib.pathname2url( program_path( 'mathjax/MathJax.js')) + r'?config=TeX-AMS-MML_HTMLorMML.js' head.append(mathjaxScript) # Use this div to make the text a whole lot bigger div = etree.SubElement(body, 'div') div.attrib['style'] = r'font-size: 250%' # Get MathML mathML = etree.fromstring(mathml) div.append(mathML) url = temp_path('import') baseUrl = QtCore.QUrl.fromLocalFile(url) # Create the web view webView = QWebView() webView.setHtml(html.tostring(root), baseUrl) # Create my widgets self.layout.addSpacing(50) self.layout.addWidget(webView) self.layout.setStretch(0, 1)
def _renderMathSVGToPNG(self, svg, defXMLs): ''' Renders the Math SVG (an lxml Element) into a PNG. Returns the bytestring containing the PNG data. ''' # Create my own SVG with valid namespaces SVG_NS = '{http://www.w3.org/2000/svg}' XLINK_NS = '{http://www.w3.org/1999/xlink}' NS_MAP = {None: SVG_NS[1:-1], 'xlink': XLINK_NS[1:-1]} myMath = etree.Element('{0}svg'.format(SVG_NS), nsmap=NS_MAP) # Copy all attributes for attr in svg.attrib.keys(): try: myMath.attrib[attr] = svg.attrib[attr] except: pass # Copy all elements for m in svg: myMath.append(m) # Change the viewbox attribute of <svg> to viewBox if 'viewbox' in myMath.attrib: data = myMath.get('viewbox') myMath.attrib.pop('viewbox') myMath.set('viewBox', data) # Insert the defs into my math equation myDef = etree.SubElement(myMath, 'defs') for d in defXMLs: for p in d: myDef.append(etree.fromstring(etree.tostring(p))) # In my math equation, every <use href> must be changed to # <use xlink:href> uses = myMath.xpath('.//use[@href]') for u in uses: data = u.get('href') u.attrib.pop('href') u.set('{0}href'.format(XLINK_NS), data) # Change the color of every element in the svg to the text color defined # in user preferences strokes = myMath.xpath(".//*[@stroke]") fills = myMath.xpath(".//*[@fill]") for s in strokes: if not ('none' in s.get('stroke')): s.set( 'stroke', self._configuration._createRGBStringFromQColor( self._configuration.color_contentText)) for f in fills: if not ('none' in f.get('fill')): f.set( 'fill', self._configuration._createRGBStringFromQColor( self._configuration.color_contentText)) # Write to temp file, run CairoSVG through it, then push it out with open(misc.temp_path('tmp.svg'), 'wb') as f: f.write(etree.tostring(myMath, pretty_print=True)) tmpURL = urlparse.urljoin( 'file:', urllib.pathname2url(misc.temp_path('tmp.svg'))) return cairosvg.svg2png(url=tmpURL)
def speakToFile(self, mp3Path, speechGenerator, progressCallback, labelCallback, checkStopFunction): ''' Writes the speech output given by the speech generator as an MP3 file that will be saved to mp3Path. The speech generator should generate tuples of the following: ('speech', 'label') The progressCallback should be a function that takes an int from 0-100, 100 being when it is done. The checkStopFunction returns a boolean value saying whether we need to stop creation, False being don't stop, and True being stop. ''' pythoncom.CoInitialize() saveFileStream = SpFileStream() saveFileStream.Format.Type = constants.SAFT32kHz16BitStereo saveFileStream.Open(temp_path('tmp.wav'), 3) self._voice = SpVoice() self._voice.AudioOutputStream = saveFileStream self._voice.EventInterests = constants.SVEAllEvents self._voice.AlertBoundary = constants.SVEPhoneme # SVEPhoneme if len(self._voiceId) > 0: token = self.voiceTokenFromId(self._voiceId) self._voice.Voice = token self._voice.Volume = self._volume self._voice.Rate = self._rate # Voice events for updating the progress thing advisor = win32com.client.WithEvents(self._voice, SAPIEventSink) advisor.setDriver(self) # Create the output list from generator so we can track its progress outputList = [] for speech in speechGenerator: outputList.append(speech) labelCallback('Speaking into WAV...') for i in range(len(outputList)): progressCallback(int(float(i) / len(outputList) * 69.0)) self._voice.Speak(outputList[i][0], 1) while not self._voice.WaitUntilDone(10): if checkStopFunction(): break if checkStopFunction(): break saveFileStream.Close() progressCallback(69) if not checkStopFunction(): # Then convert it to MP3 labelCallback('Converting to MP3...') lameExe = '' if '64' in platform.architecture()[0]: lameExe = program_path('src/lame_64.exe') else: lameExe = program_path('src/lame_32.exe') startupInfo = subprocess.STARTUPINFO() startupInfo.dwFlags = subprocess.STARTF_USESTDHANDLES | subprocess.STARTF_USESHOWWINDOW startupInfo.wShowWindow = subprocess.SW_HIDE lameCommand = lameExe + ' -h "' + temp_path( 'tmp.wav') + '" "' + mp3Path + '"' ps = subprocess.Popen(lameCommand, stdout=subprocess.PIPE, stderr=subprocess.PIPE, startupinfo=startupInfo) while ps.poll() == None: if checkStopFunction(): ps.terminate() break out = ps.stderr.readline() if re.search(r'\([0-9]+%\)', out) != None: percent = int( float(re.search(r'\([0-9]+%\)', out).group(0)[1:-2]) * 0.3) progressCallback(69 + percent) progressCallback(100)
def speakToFile(self, mp3Path, speechGenerator, progressCallback, labelCallback, checkStopFunction): ''' Writes the speech output given by the speech generator as an MP3 file that will be saved to mp3Path. The speech generator should generate tuples of the following: ('speech', 'label') The progressCallback should be a function that takes an int from 0-100, 100 being when it is done. The checkStopFunction returns a boolean value saying whether we need to stop creation, False being don't stop, and True being stop. ''' self._tts.stopSpeaking() try: os.remove(temp_path('tmp.aiff')) except OSError: pass aiffPath = unicode(temp_path('tmp.aiff')) # Create a single string that will be sent to the TTS myString = '' labelCallback('Preparing speech...') for speech in speechGenerator: myString += speech[0] + '. ' myString = myString.replace('..', '.') if checkStopFunction(): break if not checkStopFunction() and len(myString) > 0: progressCallback(30) labelCallback('Speaking into AIFF...') # Create my URL object url = NSURL.alloc() url.initFileURLWithPath_(aiffPath) # Speak string into TTS success = self._tts.startSpeakingString_toURL_(myString, url) while self._tts.isSpeaking() and not checkStopFunction(): progressCallback(30) time.sleep(0.05) progressCallback(60) # Convert to MP3 if not checkStopFunction(): labelCallback('Converting to MP3...') lameExe = '"' + program_path('src/lame_mac') + '"' lameCommand = lameExe + ' -h "' + aiffPath + '" "' + mp3Path + '"' ps = subprocess.Popen(lameCommand, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) while ps.poll() == None: if checkStopFunction(): ps.terminate() break out = ps.stderr.readline() if re.search(r'\([0-9]+%\)', out) != None: percent = int( float( re.search(r'\([0-9]+%\)', out).group(0)[1:-2]) * 0.3) progressCallback(69 + percent) progressCallback(100)
import os import subprocess import misc UPDATE_URL = r'https://archive.org/download/CARSetup64/' #UPDATE_URL = r'file:///W:/Nifty%20Prose%20Articulator/' # For testing purposes # Get the correct setup file depending on architecture SETUP_FILE = '' if platform.system() == 'Windows': if platform.architecture()[0] == '64bit': SETUP_FILE = UPDATE_URL + 'CAR_Setup_64.exe' elif platform.system() == 'Darwin': SETUP_FILE = UPDATE_URL + 'Central_Access_Reader.dmg' SETUP_TEMP_FILE = misc.temp_path( os.path.join('update', os.path.basename(SETUP_FILE))) VERSION_TEMP = misc.temp_path(os.path.join('update', 'version.txt')) VERSION_THERE = UPDATE_URL + 'version.txt' VERSION_HERE = misc.program_path('version.txt') class GetUpdateThread(Thread): ''' Used to check to see if there is an update for this program. If there is, then it will check to see if it the update was already downloaded. Then, it will prompt the GUI to either ask the user to download it or to install the update. ''' def __init__(self, updateCallback): Thread.__init__(self)
def saveToFile(self, filePath): print 'Saving config...' root = etree.Element("Configuration") # Speech Settings volumeElem = etree.SubElement(root, 'Volume') volumeElem.text = str(self.volume) rateElem = etree.SubElement(root, 'Rate') rateElem.text = str(self.rate) voiceElem = etree.SubElement(root, 'Voice') voiceElem.text = self.voice pauseElem = etree.SubElement(root, 'PauseLength') pauseElem.text = str(self.pause_length) elem = etree.SubElement(root, 'TagImage') if self.tag_image: elem.text = '1' else: elem.text = '0' elem = etree.SubElement(root, 'TagMath') if self.tag_math: elem.text = '1' else: elem.text = '0' elem = etree.SubElement(root, 'MathDatabase') elem.text = self.math_database # Highlighter Settings elem = etree.SubElement(root, 'EnableTextHighlight') if self.highlight_text_enable: elem.text = '1' else: elem.text = '0' elem = etree.SubElement(root, 'EnableLineHighlight') if self.highlight_line_enable: elem.text = '1' else: elem.text = '0' # Color Settings colorRoot = etree.SubElement(root, 'Colors') elem = etree.SubElement(colorRoot, 'ContentText') elem.text = self._createCommaSeparatedFromQColor(self.color_contentText) elem = etree.SubElement(colorRoot, 'ContentBackground') elem.text = self._createCommaSeparatedFromQColor(self.color_contentBackground) elem = etree.SubElement(colorRoot, 'HighlightText') elem.text = self._createCommaSeparatedFromQColor(self.color_highlightText) elem = etree.SubElement(colorRoot, 'HighlightBackground') elem.text = self._createCommaSeparatedFromQColor(self.color_highlightBackground) elem = etree.SubElement(colorRoot, 'HighlightLineText') elem.text = self._createCommaSeparatedFromQColor(self.color_highlightLineText) elem = etree.SubElement(colorRoot, 'HighlightLineBackground') elem.text = self._createCommaSeparatedFromQColor(self.color_highlightLineBackground) # Font settings fontRoot = etree.SubElement(root, 'Fonts') elem = etree.SubElement(fontRoot, 'All') elem.text = self.font_all # Zoom settings zoomRoot = etree.SubElement(root, 'Zooms') elem = etree.SubElement(zoomRoot, 'Content') elem.text = str(self.zoom_content) elem = etree.SubElement(zoomRoot, 'Navigation') elem.text = str(self.zoom_navigation_ptsize) # Search Settings searchRoot = etree.SubElement(root, 'Search') elem = etree.SubElement(searchRoot, 'WholeWord') if self.search_whole_word: elem.text = '1' else: elem.text = '0' elem = etree.SubElement(searchRoot, 'MatchCase') if self.search_match_case: elem.text = '1' else: elem.text = '0' # Show Tutorial elem = etree.SubElement(root, 'ShowTutorial') if self.showTutorial: elem.text = '1' else: elem.text = '0' configFile = open(filePath, 'w') configFile.write(etree.tostring(root, pretty_print=True)) configFile.close() outtext = self._writeCSS() cssPath = temp_path('import/defaultStyle.css') if not os.path.exists(cssPath): os.makedirs(os.path.dirname(cssPath)) cssFile = open(cssPath, 'w') cssFile.write(outtext) cssFile.close()
''' Created on Jul 11, 2013 @author: Spencer Graffe ''' import os import traceback from lxml import etree from lxml import html as HTML from mathtype.parser import parseWMF, MathTypeParseError from misc import program_path, temp_path, REPORT_BUG_URL from cStringIO import StringIO # The path to this particular module ROOT_PATH = program_path('src/docx') IMPORT_FOLDER = temp_path('import') # This dictionary holds image file extensions that must be converted to another # image type because the WebView doesn't support displaying it IMAGE_TRANSLATION = {'.emf': '.png'} CHARACTER_TRANSLATION = [(unichr(8208), '-')] # Get my OMML to MathML stylesheet compiled ommlXSLTPath = os.path.join(ROOT_PATH, 'OMMLToMathML.xsl') f = open(ommlXSLTPath, 'r') xslRoot = etree.parse(f) ommlTransform = etree.XSLT(xslRoot) f.close()