示例#1
0
class MainWindow(QtGui.QMainWindow):
    def __init__(self, parent=None,debug=False,filePath=None):
        """
        MainWindow constructor
        """

        QtGui.QMainWindow.__init__(self)

        ## variables
        self.appName = "lpEdit"
        self.controller = Controller(debug=debug)
        self.nga = NoGuiAnalysis(self.controller,mainWindow=self)
        self.setWindowTitle(self.appName)
        screen = QtGui.QDesktopWidget().screenGeometry()
        self.screenWidth = screen.width()
        self.screenHeight = screen.height()
        self.mainWidget = QtGui.QWidget(self)
        self.preferences = None
        self.progressBar = None
        self.sphinxLogs = {}
        self.newProject = None
        self.tabWidget = None
        self.titleLabel = None
        self.unsaved = []

        ## initialize widgets
        self.controller.reset_all()
        self.init_button_dock()
     
        ## initialize all main widgets
        self.transitions = Transitions(self)

        ## initialize menu bar
        create_menubar_toolbar(self)

        ## ensure we have absolute file path
        if filePath != None:
            filePath =  os.path.realpath(filePath)

        if filePath == None:
            self.transitions.move_to_logo()
        elif filePath != None and os.path.exists(filePath) == False:
            print "WARNING: MainWindow -- invalid file path specified as input"
            print 'skipping...'
        else:
            self.transitions.add_new_editor_tab(filePath)
            self.transitions.move_to_editor()
            
        ## finalize layout
        self.show()
        self.showMaximized()

    def load_file(self,filePath,fileLang=None):
        '''
        load a given file path both for the controller and the tabs
        load file is called when a tab widget is already present 
        '''

        ## ensure we have absolute file path 
        if filePath != None:
            filePath = os.path.realpath(filePath)

        ## ensure the path exists
        if filePath == None or os.path.exists(filePath) == False:
            print "WARNING: MainWindow.load_file -- bad file path specified"
            print "...", filePath
            return

        ## ensure the file is not already loaded
        if filePath in self.controller.filePathList:
            errMsg = "Cannot load file: file of same name is already loaded"
            self.display_warning(errMsg)
            return

        ## ensure we do not have more than the max number of documents
        numActive = self.controller.get_number_active_files()
        if int(numActive) == int(self.controller.maxDocuments):
            self.display_info("The maximum number of documents are open\nClose a document an then try again")
            return
        
        ## load files
        self.nga.load_file(filePath,fileLang=fileLang)
        
    def ensure_tab_is_current(self):
        """
        action to take on user changing current file index
        """

        currentIndex = self.tabWidget.currentIndex()
    
        self.controller.currentFileIndex = currentIndex
        fileLang = self.controller.fileLangList[currentIndex]
        fileName = self.controller.fileNameList[currentIndex]
        
        if str(fileName) == 'None':
            return
            

        if re.search("\.rnw|\.nw",fileName,flags=re.IGNORECASE):
            reportType = "PDF"
        else:
            reportType = "HTML"
        self.bDock.reportSelector.setCurrentIndex(self.bDock.reportList.index(reportType))

        if fileLang != None:
            self.bDock.langSelector.setCurrentIndex(self.bDock.langList.index(fileLang))

    def remove_tab(self,fileName=None):
        """
        removes a tab from self.tabWidget and calls appropriate cleanup functions
        """

        if self.transitions.isEditor == False:
            return

        if fileName not in self.controller.fileNameList:
            print "ERROR: MainWindow -- trying to remove invalid tab fileName"
            return

        if fileName == None:
            currentIndex = self.tabWidget.currentIndex()
            fileName = self.controller.fileNameList[currentIndex]

        indexToRemove = self.controller.fileNameList.index(fileName)
        self.tabWidget.removeTab(indexToRemove)
        self.controller.remove_file(fileName)
        #self.ensure_tab_is_current()
        self.transitions.move_to_editor()


    def create_statusbar(self):
        """
        create the bottom status bar
        """

        self.sizeLabel = QtGui.QLabel()
        self.sizeLabel.setFrameStyle(QtGui.QFrame.StyledPanel|QtGui.QFrame.Sunken)
        self.status = self.statusBar()
        self.status.setSizeGripEnabled(False)
        self.status.addPermanentWidget(self.sizeLabel)
        self.status.showMessage("Ready", 5000)

    def init_button_dock(self):
        """
        initialize the button dock
        """

        self.buttonDock = QtGui.QDockWidget(self)
        self.buttonDock.setObjectName("ButtonDockWidget")
        self.buttonDock.setAllowedAreas(QtCore.Qt.TopDockWidgetArea|QtCore.Qt.BottomDockWidgetArea)
        self.bDock = ButtonDock(mainWindow=self,buttonSize=0.09*self.screenWidth)

        hbl1 = QtGui.QHBoxLayout()
        hbl1.setAlignment(QtCore.Qt.AlignLeft)
        hbl1.addWidget(self.bDock)
        vbl = QtGui.QHBoxLayout()
        vbl.addLayout(hbl1)
        vbl.setAlignment(QtCore.Qt.AlignLeft)

        self.buttonDock.setWidget(self.bDock)
        self.addDockWidget(QtCore.Qt.TopDockWidgetArea, self.buttonDock)
        self.buttonDock.setMaximumHeight(0.09 * self.screenHeight)

    def set_editing_mode(self):
        '''
        adds a star when editing doc
        '''

        self.ensure_tab_is_current()
        fileIndex = self.controller.currentFileIndex
        editor = self.controller.editorList[fileIndex]
        fileName = self.controller.fileNameList[fileIndex]
        
        if fileName == None:
            return

        if fileName not in self.unsaved:
            self.tabWidget.setTabText(fileIndex,fileName+"*")
            self.unsaved.append(fileName)

    def help_about(self):
        """
        Function to display help information
        """

        QtGui.QMessageBox.about(self, "About %s"%self.appName,
                                """<b>%s</b> v %s
                                <p>About:This application can be used to perform
                                literate programming via Sweave and Sphinx.
                                <p>License: <a href='http://www.gnu.org/licenses/gpl-3.0.txt'>The GNU General Public License v3.0</a>  
                                <p>Development: 
                                <a href='http://bitbucket.org/ajrichards/reproducible-research'>http://bitbucket.org/ajrichards/reproducible-research</a> 
                                <p>Documentation: 
                                <a href='http://ajrichards.bitbucket.org/lpEdit/index.html'>http://ajrichards.bitbucket.org/lpEdit/index.html</a> 
                                <p>Python %s
                                <p>Qt     %s
                                <p>PyQt   %s  
                                <p>System %s
                                """ % (self.appName,
                                       self.controller.version, platform.python_version(),
                                       QT_VERSION_STR, PYQT_VERSION_STR, platform.system()))

    def open_file_callback(self):
        """
        callback function to open a *.nw, *.rnw or *.rst file
        """

        defaultDir = os.getcwd()
        if os.path.split(defaultDir)[1] in ["_sphinx","_latex"]:
            defaultDir = os.path.split(defaultDir)[0]

        fileFilter = "*.rst;;*.rnw;;*.nw;;*"

        inputFilePath = QtGui.QFileDialog.getOpenFileName(self,'Open file(s)',defaultDir,fileFilter)

        ## return if user aborts
        if inputFilePath == '':
            return

        inputFilePath = str(inputFilePath)
        if not re.search("\.rst|\.Rnw|\.rnw|\.nw",os.path.split(inputFilePath)[-1]):
            errMsg = "loaded file is of unknown extension\n" + inputFilePath
            print "WARNING: ", errMsg 
            self.display_warning(errMsg)
            return

        self.transitions.add_new_editor_tab(inputFilePath)
        self.transitions.move_to_editor()

        ## move to opened tab
        newIndex = self.controller.fileNameList.index(os.path.split(inputFilePath)[-1])
        self.tabWidget.setCurrentIndex(newIndex)
        self.ensure_tab_is_current()


    def _file_save(self,fileIndex):
        """
        lpEdits internal file save
        """

        fileName = self.controller.fileNameList[fileIndex]
        filePath = self.controller.filePathList[fileIndex]
        editor = self.controller.editorList[fileIndex]
        currentText = editor.get_text()
        fid = open(filePath,'w')
        
        ## remove carriage returns
        if re.search("\r",currentText):
            currentText = re.sub("\r+","",currentText)

        fid.write(currentText)
        fid.close()

    def file_save(self,display=True):
        '''
        saves the file in the current tab as itself
        '''

        self.ensure_tab_is_current()
        fileIndex = self.controller.currentFileIndex
        if self.controller.fileNameList[fileIndex] == None:
            self.display_info("A valid file must be loaded before saving")
            return

        templatesDir = self.controller.get_templates_dir()
        currentFilePath = self.controller.filePathList[fileIndex]
        currentFileName = self.controller.fileNameList[fileIndex]
        if os.path.join(templatesDir,currentFileName) == currentFilePath:
            self.display_info("Cannot overwrite template -- use 'Save As'")
            return

        self._file_save(fileIndex)

        fileName = self.controller.fileNameList[fileIndex]
        if fileName in self.unsaved:
            self.unsaved.remove(fileName)
            self.tabWidget.setTabText(fileIndex,fileName)

        if display == True:
            self.display_info("Progress saved")

    def file_save_as(self):
        """
        saves the file in the current tab as another file
        """

        self.ensure_tab_is_current()
        if self.controller.fileNameList[self.controller.currentFileIndex] == None:
            self.display_info("A valid file must be loaded before saving")
            return

        currentFilePath = self.controller.filePathList[self.controller.currentFileIndex]
        currentFileName = self.controller.fileNameList[self.controller.currentFileIndex]
        currentEditor = self.controller.editorList[self.controller.currentFileIndex]
        currentText = currentEditor.get_text()

        defaultDir = os.path.split(currentFilePath)[0]
        if re.search("\.rnw",currentFileName,flags=re.IGNORECASE):
            fileFilter = "*.rnw;;*.Rnw"
        elif re.search("\.nw",currentFileName,flags=re.IGNORECASE):
            fileFilter = "*.nw"
        else:
            fileFilter = "*.rst"
      
        newFilePath, extension = QtGui.QFileDialog.getSaveFileNameAndFilter(self,'Save As',defaultDir,fileFilter)
        newFilePath = str(newFilePath)
        
        if newFilePath == '':
            return

        ## if user does not provide an extension then default to template ext
        if not re.search("\.rnw|\.nw|\.rst",newFilePath,flags=re.IGNORECASE):
            if  re.search("\.rnw",currentFileName,flags=re.IGNORECASE):
                newFilePath = newFilePath + ".rnw"
            elif  re.search("\.nw",currentFileName,flags=re.IGNORECASE):
                newFilePath = newFilePath + ".nw"
            else:
                newFilePath = newFilePath + ".rst"
                
        ## ensure file extension is valid
        if not re.search("\.rnw|\.nw|\.rst",newFilePath,flags=re.IGNORECASE):
            msg = "lpEdit only works with *.rnw, *.nw and *.rst files"
            msg += "You may resave using the appropriate extension"
            self.display_warning(msg)
            return
    
        ## ensure that user preserves file extension
        msg = "To save you must preserve the file extension<p>"
        msg += "e.g. a *.rst file must be saved as a *.rst file<p>"
        msg += "Use a different template if necessary"
        if re.search("\.rnw",newFilePath,flags=re.IGNORECASE) and not re.search("\.rnw",currentFileName,flags=re.IGNORECASE):
            self.display_warning(msg)
            return
        if re.search("\.rst",newFilePath,flags=re.IGNORECASE) and not re.search("\.rst",currentFileName,flags=re.IGNORECASE):
            self.display_warning(msg)
            return
        if re.search("\.nw",newFilePath,flags=re.IGNORECASE) and not re.search("\.nw",currentFileName,flags=re.IGNORECASE):
            self.display_warning(msg)
            return

        fid = open(newFilePath,'w')
        fid.write(currentText)
        fid.close()

        ## load the new file
        self.transitions.add_new_editor_tab(newFilePath)
        self.transitions.move_to_editor()

        ## remove the old tab
        #self.remove_tab(currentFileName)

        newIndex = self.controller.fileNameList.index(os.path.split(newFilePath)[-1])
        self.tabWidget.setCurrentIndex(newIndex)
        self.ensure_tab_is_current()

        self.display_info("File saved")

    def file_print(self):
        self.display_info("This function is not yet implemented")
    
    def display_info(self,msg):
        """
        display info via a message box
        generic function to display info to user
        """
        reply = QtGui.QMessageBox.information(self,'Information',msg)

    def display_warning(self,msg):
        """
        display warning via a message box
        generic function to display a warning to user
        """
        reply = QtGui.QMessageBox.warning(self, "Warning", msg)

    def close_app(self):
        """
        callback function to close lpEdit
        asks user about saving if there are unsaved docs open
        """
        
        if len(self.unsaved) == 0:
            self.close()
            return
            
        reply = QtGui.QMessageBox.question(self, self.controller.appName,
                                           "There are unsaved files are you sure you want to exit?", 
                                           QtGui.QMessageBox.Yes, QtGui.QMessageBox.No)
        if reply == QtGui.QMessageBox.Yes:
            self.close()
            return

    def generic_callback(self):
        self.display_info("This function is not yet implemented")
示例#2
0
class NoGuiAnalysis():

    def __init__(self,controller=None,mainWindow=None):
      
        ## input variables
        if controller == None:
            self.controller = Controller()
        else:
            self.controller = controller
        self.mainWindow = mainWindow
        self.validLanguages = ['r','python']
        self.sphinxLog = None
        self.goFlag = False
        self.reload_program_paths()
        
    def reload_program_paths(self):
        """
        function to update the paths to programs for system calls
        """
        
        ## ensure that the log file is loaded
        if len(self.controller.log.log.items()) < 1:
           self.controller.log = Logger() 

        self.rPath = self.controller.get_r_path(mainWindow=self.mainWindow)
        self.pythonPath = self.controller.get_python_path(mainWindow=self.mainWindow)
        self.sphinxPath = self.controller.get_sphinx_path(mainWindow=self.mainWindow)
        self.latexPath = self.controller.get_latex_path()
        self.parsePath = os.path.join(self.controller.baseDir,"ParseEmbedded.py")
        self.latex2htmlPath = self.controller.get_latex2html_path()

    def build(self,fileName=None,verbose=False):
        """
        generic command to build a rst,nw or rnw document
        """

        ## variables
        self.goFlag = False
        if self.mainWindow != None:
            self.mainWindow.ensure_tab_is_current()
        
        ## if a fileName is specified the set the current index
        if fileName != None and fileName in self.controller.fileNameList:
            currentIdx = self.controller.fileNameList.index(fileName)
            self.controller.currentFileIndex = currentIdx
        
        currentIdx = self.controller.currentFileIndex
        fileName = self.controller.fileNameList[currentIdx]
        filePath = self.controller.filePathList[currentIdx]

        fileLanguage = self.controller.fileLangList[currentIdx]
        self.reload_program_paths()
        goFlag = None

        if self.mainWindow != None:
            editor = self.mainWindow.controller.editorList[currentIdx] 
            editor.clear_messages()
        
        self.output_text("BUILDING... %s"%fileName)

        ## error checking
        isClean = self.controller.sanitize_check(filePath)
        if isClean == False:
            msg = "Invalid file/dir name\n"
            msg += "%s\nremove characters like '$','#' and '&' then try again"%(filePath) 
            self.display_error(msg)
            return

        isActive = self.is_active_project(filePath)
        if not isActive:
            return
        isTemplate = self.is_template()
        if isTemplate == True:
            return

        fileLanguage = fileLanguage.lower()
        if fileLanguage not in self.validLanguages:
            msg = "Valid languages are %s not %s"%(self.validLanguages,fileLanguage)
            self.display_error(msg)
            return

        ## save file
        if self.mainWindow != None:
            self.mainWindow.file_save(display=False)

        ## run the appropriate builder
        if re.search("\.rst",fileName,flags=re.IGNORECASE):
            self.build_rst(verbose=verbose)
        elif re.search("\.rnw|\.nw",fileName,flags=re.IGNORECASE):
            self.build_nw(verbose=verbose)
        else:
            msg = "Invalid file name extension\n"
            msg +="...lpEdit cannot build\n"
            msg +=filePath
            self.display_error(msg)

    def load_file(self,filePath,fileLang=None):
        '''
        use the controller to load a specified file
        '''

        filePath = os.path.realpath(filePath)

        if not os.path.exists(filePath):
            print("ERROR: invalid file path specified for load")
            print("... %s"%filePath)
            return
        
        isValid = self.controller.load_file(filePath,fileLang=fileLang)
        if isValid == False:
            print "ERROR: controller could not load specified file"
            print "\t", filePath

    def clean_file(self,filePath,verbose=False):
        '''
        cleans a directory of its files -- function used with unittests
        '''
        
        self.controller.clean_file(filePath)

    def output_text(self,txt):
        currentIdx = self.controller.currentFileIndex
        
        if self.mainWindow != None:
            if self.mainWindow.controller.editorList[currentIdx].textScreen.showMessages == False:
                self.mainWindow.controller.editorList[currentIdx].textScreen.toggle_message_btn()
            self.mainWindow.controller.editorList[currentIdx].textScreen.add_text(txt)
        else:
            print txt

    def copy_included_files(self,filePath,dirPath):
        """
        Copy files that are included with the keyword INCLUDE
        The source file path is given and it is scanned for INCLUDE
        Each include may be multiple file paths (comma delim)
        """
        
        baseDir = os.path.split(filePath)[0]
        
        ## adjust for subdirectories
        if os.path.split(baseDir)[1] != os.path.split(os.path.split(dirPath)[0])[1]:
            subdir = os.path.split(baseDir)[1]
            targetDir = os.path.join(dirPath,subdir)
        else:
            targetDir = dirPath
            subdir = None

        fid = open(filePath,'r')
        includedFiles = []
        found = False
        for linja in fid:
            if re.search("^%|^\.\. ",linja) and re.search("INCLUDE",linja):
                linja = re.sub("INCLUDE[\W|\w]","",linja)
                linja = re.sub("\%|\s+|^\.\.","",linja)
                found = True
                linja = re.split(",",linja)
                for includedFile in linja:
                    if os.path.exists(includedFile):
                        includedFiles.append(os.path.realpath(includedFile))
                    else:
                        includedFilePath = os.path.join(baseDir,includedFile)
                        includedFiles.append(os.path.realpath(includedFilePath))

        for includedFilePath in includedFiles:
            includedFilePath = includedFilePath
            includedFileName = os.path.split(includedFilePath)[-1]
            includedFileDir = os.path.split(includedFilePath)[-1]
            newFilePath = os.path.join(targetDir,includedFileName)

            if not os.path.exists(includedFilePath):
                msg = "Invalid INCLUDE path...\n"         
                msg += includedFilePath
                if self.mainWindow != None:
                    self.mainWindow.display_warning(msg)
                else:
                    print msg
                return False

            if os.path.islink(newFilePath):
                os.remove(newFilePath)
            if os.path.exists(newFilePath):
                os.remove(newFilePath)

            self.output_text("INCLUDE: %s \n...%s"%(includedFilePath,newFilePath))

            os.symlink(includedFilePath,newFilePath)

        return True

    def is_active_project(self,currentFilePath):
        """
        check for an active project
        """
        if currentFilePath == '' or currentFilePath == None:
            msg = "Load or create a new file before compiling code"
            self.display_error(msg)
            return False

        return True

    def is_template(self):
        """
        checks to see if currentFile is a template or not
        """
        templatesDir = self.controller.get_templates_dir()
        currentFilePath = self.controller.filePathList[self.controller.currentFileIndex]
        currentFileName = self.controller.fileNameList[self.controller.currentFileIndex]

        if os.path.join(templatesDir,currentFileName) == currentFilePath:
            msg = "Use 'Save As' before trying to work with template"
            self.display_error(msg)
            return True

        return False

    def display_error(self,msg):
        """
        generic function to display an error
        """
        if self.mainWindow != None:
            self.mainWindow.display_warning(re.sub("\n","<p>",msg))
        else:
            print "ERROR: ", msg

    def build_nw(self,verbose=True):
        """
        uses system calls to compile nw or sweave code
        """

        ## variables
        templatesDir = self.controller.get_templates_dir()
        currentIdx = self.controller.currentFileIndex
        filePath = self.controller.filePathList[currentIdx]
        fileName = self.controller.fileNameList[currentIdx] 
        fileLanguage = self.controller.fileLangList[currentIdx]
        fileLanguage = fileLanguage.lower()
        filePathBase = os.path.split(filePath)[0]
        texFileName = re.sub("\.rnw|\.nw|\.rst",".tex",fileName,flags=re.IGNORECASE)
        dirPath = self.controller.ensure_dir_present(filePath)
        assemblePath = os.path.join(self.controller.baseDir,"AssembleOutNW.py")

        ## ensure we are using the correct builder
        if not re.search("\.nw|\.rnw",fileName,flags=re.IGNORECASE):
            msg = "NoGuiAnalysis: Incorrect builder -- skipping"
            self.display_error(msg)
            return

        ## ensure the correct builder is being used (based on extension)
        if re.search("\.rnw",fileName,flags=re.IGNORECASE) and fileLanguage != 'r':
            msg = "Sweave styled documents cannot contain code\n"
            msg += "other than R. \nSave the document as a *.nw file and try again"
            self.display_error(msg)
            return
        elif re.search("\.rnw",fileName,flags=re.IGNORECASE):
            builder = 'sweave'
        else:
            builder = 'nw'
        
        ## copy target file to dir
        targetFilePath = os.path.join(dirPath,fileName)
        shutil.copy(filePath,targetFilePath)

        ## copy included files
        goFlag = self.copy_included_files(filePath,dirPath)
        if goFlag == False:
            errMsg = "Build aborted"
            self.display_error(errMsg)
            return False
 
        ## move a copy of each sty file into the dir
        styfilesDir = self.controller.get_styfiles_dir()
        for styfile in os.listdir(styfilesDir):
            if not re.search("\.sty",styfile):
                continue
            if os.path.exists(os.path.join(dirPath,styfile)) == False:
                shutil.copy(os.path.join(styfilesDir,styfile),os.path.join(dirPath,styfile))

        ## paths
        if fileLanguage == 'python':
            chunksFilePath = os.path.join(dirPath,"chunks.py")
            outFilePath = os.path.join(dirPath,"outPy.txt")
            langCmd = self.pythonPath
        elif fileLanguage == 'r':
            chunksFilePath = os.path.join(dirPath,"chunks.R")
            outFilePath = os.path.join(dirPath,"outR.txt")
            langCmd = self.rPath+'script'

        ## remove old versions of the files
        for fname in [chunksFilePath,outFilePath,os.path.join(dirPath,texFileName)]:
            if os.path.exists(fname):
                os.remove(fname)

        if builder == 'sweave':
            self.output_text('BUILDING WITH SWEAVE...')
            compileCmd = '"%s" CMD Sweave "%s"'%(self.rPath,targetFilePath)
            self.run_subprocess(compileCmd)

            ## move the output to build directory
            tmpTex = os.path.join(os.getcwd(),texFileName)
            if os.path.exists(tmpTex):
                shutil.move(tmpTex,os.path.join(dirPath,texFileName))

        elif builder == 'nw':
            ## extract the code
            self.output_text("EXTRACTING CODE...")
            compileCmd = '"%s" "%s" -i "%s" -o "%s"'%(self.pythonPath,self.parsePath,
                                                      targetFilePath,chunksFilePath)
            self.run_subprocess(compileCmd)
            
            ## run extracted code
            if os.path.exists(chunksFilePath):
                self.output_text("RUNNING CODE...")
                compileCmd = '"%s" "%s" > "%s"'%(langCmd,chunksFilePath,outFilePath)
                self.run_subprocess(compileCmd)
            else:
                self.output_text("EXITING EARLY... could not find extracted code")
                return False

            if self.mainWindow != None:
                self.mainWindow.transitions.update_ui()

            ## exit early on error
            goFlag = self.check_standard_error(self.stdErr)
            
            if goFlag == False:
                self.output_text("EXITING EARLY... ERROR found in embedded code")
                return False

            ## reassemble the *.tex file with code results
            if os.path.exists(outFilePath):
                self.output_text("REASSEMBLING CODE AND RESULTS...")
                compileCmd = '"%s" "%s" -i "%s" -o "%s" -l "%s"'%(self.pythonPath,assemblePath,
                                                                  targetFilePath,outFilePath,fileLanguage)
                self.run_subprocess(compileCmd)
            else:
                self.output_text("EXITING EARLY... there was a problem running the embedded code")
                return False
                
        ## check that we have a valid build
        self.goFlag = self.ensure_valid_build(os.path.join(dirPath,texFileName))

    def check_standard_error(self,stdErr):
        """
        a function that halts on certain standard error messages
        """

        if stdErr != None and re.search('Traceback|Error:|Exception occurred:',stdErr,flags=re.IGNORECASE):
            return False
        else:
            return True

    def build_rst(self,verbose=True):
        """
        uses system calls to compile a sphinx project
        """
        
        ## variables
        currentIdx = self.controller.currentFileIndex
        filePath = self.controller.filePathList[currentIdx]
        filePathBase = os.path.split(filePath)[0]
        fileName = self.controller.fileNameList[currentIdx]
        fileLanguage = self.controller.fileLangList[currentIdx]
        fileLanguage = fileLanguage.lower()
        filePathBase = os.path.split(filePath)[0]
        assemblePath = os.path.join(self.controller.baseDir,"AssembleOutRst.py")
        tmpFilePath = filePath + ".tmp"

        ## ensure we are using the correct builder
        if not re.search("\.rst",fileName,flags=re.IGNORECASE):
            msg = "NoGuiAnalysis: Incorrect builder -- skipping"
            self.display_error(msg)
            return

        ## copy included files
        dirPath = self.controller.ensure_dir_present(filePath)
        goFlag = self.copy_included_files(filePath,dirPath)
        if goFlag == False:
            errMsg = "Build aborted"
            self.display_error(errMsg)
            return

        ## move a copy of each sty file into the dir
        styfilesDir = self.controller.get_styfiles_dir()
        for styfile in os.listdir(styfilesDir):
            if not re.search("\.sty",styfile):
                continue
            if os.path.exists(os.path.join(dirPath,styfile)) == False:
                shutil.copy(os.path.join(styfilesDir,styfile),os.path.join(dirPath,styfile))

        ## initialize a sphinx project
        self.controller.initialize_sphinx_project(filePath)
        self.controller.copy_sphinx_files()
        self.sphinxLog = SphinxLogger(os.path.join(dirPath,'sphinx.log'))
        self.sphinxLog.write()

        ## ensure the current file is copied
        fileBase = os.path.split(filePath)[0]

        if fileBase != self.controller.sphinxProjectBase:
            subdirName = os.path.basename(os.path.dirname(filePath))
            targetFilePath = os.path.join(dirPath,subdirName,fileName)
        else:
            targetFilePath = os.path.join(dirPath,fileName)

        print 'copying...', targetFilePath

        shutil.copy(filePath,targetFilePath)

        ## compile
        if fileLanguage == 'python':
            chunksFilePath = os.path.join(dirPath,"chunks.py")
            outFilePath = os.path.join(dirPath,"outPy.txt")
            langCmd = self.pythonPath
        elif fileLanguage == 'r':
            chunksFilePath = os.path.join(dirPath,"chunks.R")
            outFilePath = os.path.join(dirPath,"outR.txt")
            langCmd = self.rPath+'script'

        ## remove old versions of files
        for fname in [chunksFilePath,outFilePath,tmpFilePath]:
            if os.path.exists(fname):
                os.remove(fname)

        ## extract the code from the file
        self.output_text("EXTRACTING CODE...")
        compileCmd = '"%s" "%s" -i "%s" -o "%s"'%(self.pythonPath,self.parsePath,
                                                  filePath,chunksFilePath)
        self.run_subprocess(compileCmd)

        ## run the embedded code
        if os.path.exists(chunksFilePath):
            self.output_text("RUNNING CODE (%s)..."%(fileLanguage))
            compileCmd = '"%s" "%s" > "%s"'%(langCmd,chunksFilePath,outFilePath)
            self.run_subprocess(compileCmd)
        else:
            self.output_text("EXITING EARLY... could not find extracted code")
            return False

        ## exit early on error
        goFlag = self.check_standard_error(self.stdErr)
        if goFlag == False:
            self.output_text("EXITING EARLY... ERROR found in embedded code")
            return False

        ## reassemble the *.rst file with code results
        if os.path.exists(outFilePath):
            self.output_text("\nREASSEMBLING CODE AND RESULTS...")   
            compileCmd = '"%s" "%s" -i "%s" -o "%s" -l %s'%(self.pythonPath,
                                                            assemblePath,
                                                            filePath,
                                                            outFilePath,
                                                            fileLanguage)
            self.run_subprocess(compileCmd)
        else:
            self.output_text("EXITING EARLY... there was a problem running the embedded code")
            return False
        
        ## overwrite the old rst file
        if os.path.exists(tmpFilePath):
            shutil.move(tmpFilePath,targetFilePath)
            self.goFlag = True
            self.output_text("BUILD COMPLETED SUCCESFULLY.")
            if self.mainWindow != None:
                editor = self.mainWindow.controller.editorList[currentIdx] 
                if editor.textScreen.showMessages == True:
                    editor.textScreen.toggle_message_btn()
            return True


    def show_error(self):
        """
        show error in messages
        """

        currentIdx = self.controller.currentFileIndex
        if self.mainWindow != None:
            self.mainWindow.display_info("Build did not complete correctly")
            editor = self.mainWindow.controller.editorList[currentIdx] 
            if editor.textScreen.showMessages == False:
                editor.textScreen.toggle_message_btn()
        else:
            print "WARNING: Build did not complete correctly"
        return
       
    def ensure_valid_build(self,texFilePath):
        """
        ensure build completed correctly
        """

        currentIdx = self.controller.currentFileIndex
        if not os.path.exists(texFilePath):
            self.show_error()
            return False
        else:
            self.output_text("BUILD COMPLETED SUCCESFULLY.")
            if self.mainWindow != None:
                editor = self.mainWindow.controller.editorList[currentIdx] 
                if editor.textScreen.showMessages == True:
                    editor.textScreen.toggle_message_btn()
            return True

    def on_subprocess_complete(self):
        """
        on completion of a subprocess return to editor mode
        """

        if self.mainWindow != None:
            self.mainWindow.transitions.move_to_editor()

        ## debugging
        #print 'output',self.stdOut,self.stdErr

    def run_subprocess(self,cmd,background=False,clear=True):
        self.stdErr, self.stdOut = None, None

        ## create a thread to check status of subprocess
        def target(process,nga):
            while process.thread.is_alive():
                currentIdx = nga.controller.currentFileIndex

                if nga.mainWindow != None:
                    editor = nga.controller.editorList[currentIdx] 
                    editor.clear_messages()
      
                time.sleep(1)
                nga.output_text(process.cmd)
                stdOut = process.stdOut
                stdErr = process.stdErr
                if stdOut == None or len(stdOut) == 0:
                    stdOut = ''
                if stdErr == None or len(stdErr) == 0:
                    stdErr = ''

                if stdOut != '':
                    nga.output_text("\n"+stdOut)
                if stdErr != '':
                    ## ignore certain stderr
                    if re.search("\[2K\n",stdErr):
                        stdErr = ''
                        continue

                    nga.output_text("\n"+stdErr)

            self.stdErr, self.stdOut = stdErr, stdOut
            nga.on_subprocess_complete()

        ## move to appropriate mode
        if self.mainWindow != None:
            self.mainWindow.transitions.move_to_subprocess()
            self.mainWindow.process = RunSubprocess(cmd)
            process = self.mainWindow.process
            self.mainWindow.transitions.update_ui()
        else:
            process = RunSubprocess(cmd)

        ## begin the threaded subprocess
        returnCode = process.run(timeout=None)

        ## run the process in the background
        if background == True:
            if self.mainWindow != None:
                self.mainWindow.transitions.move_to_editor()
            return True

        ## start a thread to check on process status
        if self.mainWindow != None:
            self.mainWindow.waitThread = threading.Thread(target=target(process,self))
            waitThread = self.mainWindow.waitThread
        else:
            waitThread = threading.Thread(target=target(process,self))

        waitThread.start()

    def compile_pdf(self,verbose=True,recompile=False):
        """
        uses system calls to compile the latex code to pdf
        """

        # variables
        if self.mainWindow != None:
            self.mainWindow.ensure_tab_is_current()

        currentIdx = self.controller.currentFileIndex
        filePath = self.controller.filePathList[currentIdx]
        filePathBase = os.path.split(filePath)[0]
        fileName = self.controller.fileNameList[currentIdx]

        ## error checking
        isActive = self.is_active_project(filePath)
        if not isActive:
            return
        isTemplate = self.is_template()
        if isTemplate == True:
            return

        ## clear the text
        if self.mainWindow != None:
            editor = self.mainWindow.controller.editorList[currentIdx] 
            editor.clear_messages()

        ## more variables
        dirPath = self.controller.ensure_dir_present(filePath)

        if re.search("\.rnw|\.nw",fileName,flags=re.IGNORECASE):
            texFileName = re.sub("\.rnw|\.nw",".tex",fileName,flags=re.IGNORECASE)
            texFilePath = os.path.join(dirPath,texFileName)
            pdfFileName = re.sub("\.rnw|\.nw",".pdf",fileName,flags=re.IGNORECASE)        
            pdfFileName = re.sub("\s+","_",pdfFileName)
            pdfFilePath = os.path.join(dirPath,pdfFileName)
            projectType = 'nw'
        else:
            sl = SphinxLogger(os.path.join(dirPath,'sphinx.log'))
            texFileName = sl.log['project_name'] + ".tex"
            texFilePath = os.path.join(dirPath,"_build",texFileName)
            pdfFileName = sl.log['project_name'] + ".pdf"
            pdfFileName = re.sub("\s+","_",pdfFileName)
            pdfFilePath = os.path.join(dirPath,"_build",pdfFileName)
            projectType = 'sphinx'

        ## if sphinx project
        if projectType == 'sphinx':
            self.output_text("BUILDING SPHINX (LaTeX)...")
            sl = SphinxLogger(os.path.join(dirPath,'sphinx.log'))
            texFileName = self.sphinxLog.log['project_name'] + ".tex"
            texFilePath = os.path.join(dirPath,"_build",texFileName)
        
            ## remove old versions of files
            for fname in [texFilePath]:
                if os.path.exists(fname):
                    os.remove(fname)
        
            compileCmd = "%s -b latex %s %s"%(self.sphinxPath,dirPath,os.path.join(dirPath,"_build"))
            self.run_subprocess(compileCmd)
            goFlag = self.ensure_valid_build(texFilePath)

            if goFlag == False:
                self.output_text("EXITING EARLY... Could not create tex file.")
                return False

        if not os.path.exists(texFilePath):
            errMsg = "'%s' does not exist\nDid you build the file successfully?"%(texFileName)
            self.display_error(errMsg)
            return

        ## compile
        ## with errors nonstopmode will do its best to compile, batchmode will supress pdf output
        if projectType == 'nw':
            texOut = dirPath
        else:
            texOut = os.path.join(dirPath,'_build')
        latexCompileCmd = '"%s" -interaction=nonstopmode -output-directory %s "%s"'%(self.latexPath,texOut,texFilePath)
 
        ## remove pdf files
        for fname in [pdfFilePath]:
            if os.path.exists(fname):
                os.remove(fname)
        
        ## first pass to match citations and refs
        self.run_subprocess(latexCompileCmd)
        goFlag = self.check_pdf_compile(pdfFilePath)
        if goFlag == False:
            return

        ## recompile if specified
        if recompile:
            self.run_subprocess(latexCompileCmd)

        ## check to see if there was a bib file
        bibFilePath = None
        fid = open(filePath,'r')
        for linja in fid:
            if re.search("\{.+\.bib\}",linja):
                match = re.findall("\{.+\.bib\}",linja)
                bibFileName = match[0][1:-1]
                bibFilePath = os.path.join(filePathBase,bibFileName)
        fid.close()

        ## if there was a bib
        if bibFilePath != None:
            cwd = os.getcwd()
            os.chdir(texOut)
            bibtexPath = re.sub('pdflatex','bibtex',self.latexPath)
            compileCmd = '"%s" "%s"'%(bibtexPath,texFileName[:-4])
            self.run_subprocess(compileCmd)
            os.chdir(cwd)

            ## compile twice for bib
            #if os.path.exists(pdfFilePath):
            self.run_subprocess(latexCompileCmd)
            #self.run_subprocess(latexCompileCmd)
                
        ## check to see that everything worked
        goFlag = self.check_pdf_compile(pdfFilePath)
        if goFlag == False:
            return

        ## move pdf into same directory as src file
        if os.path.exists(pdfFilePath) == False:
            print "ERROR: NoGuiAnalysis.compile_latex --- could not find pdfFileName to move"
            return

        shutil.move(pdfFilePath,os.path.join(filePathBase,pdfFileName))

    def compile_html(self,verbose=True):
        """
        use system calls to compile either latex to html or rst to html
        """

        # variables
        if self.mainWindow != None:
            self.mainWindow.ensure_tab_is_current()

        currentIdx = self.controller.currentFileIndex
        filePath = self.controller.filePathList[currentIdx]
        filePathBase = os.path.split(filePath)[0]
        fileName = self.controller.fileNameList[currentIdx]

        ## error checking
        isActive = self.is_active_project(filePath)
        if not isActive:
            return
        isTemplate = self.is_template()
        if isTemplate == True:
            return

        ## clear the text
        if self.mainWindow != None:
            editor = self.mainWindow.controller.editorList[currentIdx] 
            editor.clear_messages()

        ## more variables
        dirPath = self.controller.ensure_dir_present(filePath)
        
        ## determine the type of project 
        if re.search("\.rnw|\.nw",fileName,flags=re.IGNORECASE):
            projectType = 'latex'
        elif re.search("\.rst",fileName,flags=re.IGNORECASE):
            sl = SphinxLogger(os.path.join(dirPath,'sphinx.log'))
            projectType = 'sphinx'
        else:
            errMsg = "Invalid source file for compile_html -- skipping compile\n%s"%fileName
            self.display_error(errMsg)

        if projectType == 'sphinx':
            ## before building remove old html
            htmlFilePath =  os.path.join(dirPath,"_build","index.html")
            if os.path.exists(htmlFilePath):
                os.remove(htmlFilePath)

            ## use sphinx build to create the html document
            self.output_text("BUILDING WITH SPHINX (Sphinx)...")
            sl = SphinxLogger(os.path.join(dirPath,'sphinx.log'))
            
            compileCmd = "%s -b html %s %s"%(self.sphinxPath,dirPath,os.path.join(dirPath,"_build"))
            self.run_subprocess(compileCmd)
        else:
            htmlFileName =  re.sub("\.rnw|\.nw",".html",fileName,flags=re.IGNORECASE)
            htmlFilePath =  os.path.join(dirPath,htmlFileName)
            if os.path.exists(htmlFilePath):
                os.remove(htmlFilePath)

            ## use external program i.e. latex2html to create the html documents
            self.output_text("BUILDING HTML (LaTeX)...")
            sl = SphinxLogger(os.path.join(dirPath,'sphinx.log'))
            
            ## ensure we have valid program to build
            if self.latex2htmlPath == None:
                errMsg = "No program is specified for LaTeX to HTML conversion\nGo to Preferences"
                if self.mainWindow != None:
                    self.mainWindow.display_info(errMsg)
                else:
                    print errMsg
                return

            targetFilePath = os.path.join(dirPath,fileName)
            compileCmd = '"%s" "%s"'%(self.latex2htmlPath,targetFilePath)
            self.run_subprocess(compileCmd)

            ## point to main html file
            fileNameBase = re.sub("\.rnw|\.nw","",fileName,flags=re.IGNORECASE)
            htmlFilePath = os.path.join(dirPath,fileNameBase,'index.html')

        ## check that html  was created succesfully
        goFlag = self.check_standard_error(self.stdErr)
        
        if goFlag == False:
            self.output_text("EXITING EARLY... ERROR: html was not created succesfully")
            return False

        ## ensure html was created
        if os.path.exists(htmlFilePath) == False:        
            errMsg = "The HTML did not compile correctly \n%s"%htmlFilePath
            self.display_error(errMsg)
        else:
            if self.mainWindow != None:
                if self.controller.editorList[currentIdx].textScreen.showMessages == True:
                    self.controller.editorList[currentIdx].textScreen.toggle_message_btn()
            
    def check_pdf_compile(self,pdfFilePath):
        currentIdx = self.controller.currentFileIndex
        if not os.path.exists(pdfFilePath):
            errMsg = "LaTeX did not compile correctly"
            self.display_error(errMsg)

            if self.mainWindow != None:
                self.mainWindow.display_info(errMsg)
                if self.controller.editorList[currentIdx].textScreen.showMessages == False:
                    self.controller.editorList[currentIdx].textScreen.toggle_message_btn()
            else:
                print "ERROR: " + errMsg
            return False
        else:
            self.output_text("PDF CREATED SUCCESFULLY.")
            if self.mainWindow != None: 
                if self.controller.editorList[currentIdx].textScreen.showMessages == True:
                    self.controller.editorList[currentIdx].textScreen.toggle_message_btn()

            return True

    def view_pdf(self):
        '''
        uses system calls to view the pdf
        '''

        ## variables
        if self.mainWindow != None:
            self.mainWindow.ensure_tab_is_current()

        isTemplate = self.is_template()
        if isTemplate == True:
            return

        currentIdx = self.controller.currentFileIndex
        filePath = self.controller.filePathList[currentIdx]
        filePathBase = os.path.split(filePath)[0]
        fileName = self.controller.fileNameList[currentIdx]
        dirPath = self.controller.ensure_dir_present(filePath)
        
        ## error checking
        isActive = self.is_active_project(filePath)
        if not isActive:
            return

        ## clear the text
        if self.mainWindow != None:
            editor = self.mainWindow.controller.editorList[currentIdx] 
            editor.clear_messages()

        ## more variables 
        if re.search("\.rnw|\.nw",fileName,flags=re.IGNORECASE):
            pdfFileName = re.sub("\.rnw|\.nw",".pdf",fileName,flags=re.IGNORECASE)
        else:
            sl = SphinxLogger(os.path.join(dirPath,'sphinx.log'))
            pdfFileName = sl.log['project_name'] + ".pdf"
            
        pdfFilePath = os.path.join(filePathBase,pdfFileName)

        if not os.path.exists(pdfFilePath):
            errMsg = "'%s' does not exist\nDid you run the PDF compilation script?"%(pdfFilePath)
            self.display_error(errMsg)
            return

        pdfViewerPath = self.controller.get_pdfviewer_path()

        if pdfViewerPath == None:
            errMsg = "No pdf viewer found -- do you have one installed?"
            self.display_error(errMsg)
                
        ## view the pdf
        pdfViewerCmd = '"%s" "%s"'%(pdfViewerPath,pdfFilePath)
            
        if self.mainWindow == None:
            return

        self.run_subprocess(pdfViewerCmd,background=True)

        if self.mainWindow != None: 
            if self.controller.editorList[currentIdx].textScreen.showMessages == True:
                self.controller.editorList[currentIdx].textScreen.toggle_message_btn()
            
    def view_html(self):
        '''
        uses webbrowser to open the report
        '''

        ## variables
        if self.mainWindow != None:
            self.mainWindow.ensure_tab_is_current()

        isTemplate = self.is_template()
        if isTemplate == True:
            return

        currentIdx = self.controller.currentFileIndex
        filePath = self.controller.filePathList[currentIdx]
        filePathBase = os.path.split(filePath)[0]
        fileName = self.controller.fileNameList[currentIdx]
        dirPath = self.controller.ensure_dir_present(filePath)
        
        ## error checking
        isActive = self.is_active_project(filePath)
        if not isActive:
            return

        ## clear the text
        if self.mainWindow != None:
            editor = self.mainWindow.controller.editorList[currentIdx] 
            editor.clear_messages()

        ## open the file in a browser 
        if re.search("\.rnw|\.nw",fileName,flags=re.IGNORECASE):
            htmlFilePath = os.path.join(dirPath,re.sub("\.rnw|\.nw",".html",fileName,flags=re.IGNORECASE))
        else:
            sl = SphinxLogger(os.path.join(dirPath,'sphinx.log'))
            htmlFilePath = os.path.join(dirPath,"_build",'index.html')

        if not os.path.exists(htmlFilePath):
            errMsg = "'%s' does not exist.<p>Try HTML compilation again"%(os.path.split(htmlFilePath)[-1])
            self.display_error(errMsg)
            return

        webbrowser.open_new("file://"+os.path.realpath(htmlFilePath))

        if self.mainWindow != None: 
            if self.controller.editorList[currentIdx].textScreen.showMessages == True:
                self.controller.editorList[currentIdx].textScreen.toggle_message_btn()