Exemple #1
0
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)
Exemple #3
0
    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
Exemple #5
0
    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)
Exemple #6
0
    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)
Exemple #7
0
    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)
Exemple #8
0
    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)
Exemple #9
0
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)
Exemple #10
0
 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()