Exemple #1
0
 def __init__(self, parent):
     QsciLexerCPP.__init__(self, parent)
     self.parent = parent
     self.plainFont = QFont()
     self.plainFont.setFamily(config.fontName())
     self.plainFont.setFixedPitch(True)
     self.plainFont.setPointSize(config.fontSize())
     self.boldFont = QFont(self.plainFont)
     self.boldFont.setBold(True)
     self.setFoldCompact(True)
Exemple #2
0
    def __init__( self, parent = None, caseInsensitiveKeywords = False ):

        QsciLexerCPP.__init__( self, parent, caseInsensitiveKeywords )
        Lexer.__init__( self )

        self.commentString = "//"
        self.streamCommentString = { 'start' : '/* ',
                                     'end'   : ' */' }
        self.boxCommentString = { 'start'  : '/* ',
                                  'middle' : ' * ',
                                  'end'    : ' */' }
        return
Exemple #3
0
    def __init__(self, parent):
        QsciLexerCPP.__init__(self, parent)
        
        self.lexer = Lexer.Lexer(self.language())

        self.setDefaultPaper(self.lexer.get_globaldefault_paper())
        self.setFont(self.lexer.get_default_font())
        
        self.comment_string = QString("//")
        self.stream_comment_string = {
            'start' : QString('/* '),
            'end'   : QString(' */')
        }
	def keywords(self, sett):
		#print sett
		if sett == 1:
			#return "const int void"
			s =  QsciLexerCPP.keywords(self, sett)
			s += " HIGH LOW INPUT OUTPUT"
			return s
			
		## umm test looks same ?? and with 3 cPP return loads of stuff
		#elif sett == 3:
		#	return "pinMode digitalWrite  HIGH LOW"
		#else:
		#	return " delay HIGH LOW"
		return QsciLexerCPP.keywords(self, sett)
    def keywords(self, sett):
        #print sett
        if sett == 1:
            #return "const int void"
            s = QsciLexerCPP.keywords(self, sett)
            s += " HIGH LOW INPUT OUTPUT"
            return s

        ## umm test looks same ?? and with 3 cPP return loads of stuff
        #elif sett == 3:
        #	return "pinMode digitalWrite  HIGH LOW"
        #else:
        #	return " delay HIGH LOW"
        return QsciLexerCPP.keywords(self, sett)
 def defaultKeywords(self, kwSet):
     """
     Public method to get the default keywords.
     
     @param kwSet number of the keyword set (integer)
     @return string giving the keywords (string) or None
     """
     return QsciLexerCPP.keywords(self, kwSet)
 def find_lexer(self, extension):
     extension = extension.toLower()
     #TODO: This is horrible and evil. Fix it.
     for extensions, lexer in extension_map:
         if extension in extensions:
             return lexer()
     # Fallback
     return QsciLexerCPP()
 def __init__(self, parent=None, caseInsensitiveKeywords = False):
     """
     Constructor
     
     @param parent parent widget of this lexer
     """
     QsciLexerCPP.__init__(self, parent, caseInsensitiveKeywords)
     Lexer.__init__(self)
     
     self.commentString = QString("//")
     self.streamCommentString = {
         'start' : QString('/* '),
         'end'   : QString(' */')
     }
     self.boxCommentString = {
         'start'  : QString('/* '),
         'middle' : QString(' * '),
         'end'    : QString(' */')
     }
Exemple #9
0
        print "color" + str( style ) + "=" + colorToString( lexer.color( style ) )
        print "paper" + str( style ) + "=" + colorToString( lexer.paper( style ) )
        print "eolFill" + str( style ) + "=" + str( lexer.eolFill( style ) )
        print "font" + str( style ) + "=" + lexer.font( style ).toString()
        indexes.append( str( style ) )

    print "indexes=" + ",".join( indexes )
    print ""
    return


dumpLexer( QsciLexerPython() )
dumpLexer( QsciLexerBash() )
dumpLexer( QsciLexerBatch() )
dumpLexer( QsciLexerCMake() )
dumpLexer( QsciLexerCPP() )
dumpLexer( QsciLexerCSharp() )
dumpLexer( QsciLexerCSS() )
dumpLexer( QsciLexerDiff() )
dumpLexer( QsciLexerD() )
dumpLexer( QsciLexerFortran77() )
dumpLexer( QsciLexerFortran() )
dumpLexer( QsciLexerHTML() )
dumpLexer( QsciLexerIDL() )
dumpLexer( QsciLexerJava() )
dumpLexer( QsciLexerJavaScript() )
dumpLexer( QsciLexerLua() )
dumpLexer( QsciLexerMakefile() )
dumpLexer( QsciLexerPascal() )
dumpLexer( QsciLexerPerl() )
dumpLexer( QsciLexerPostScript() )
Exemple #10
0
    def __init__(self, parent=None, fileName=None, readOnlyFiles=[]):
        '''
        Constructor
        '''
        super(CppEditor, self).__init__(parent)
        self.parent = parent
        self.roFiles = readOnlyFiles

        self.setAcceptDrops(False)  # drag&drop is on its parent

        # Set the default font
        font = QtGui.QFont()
        font.setFamily('Courier')
        font.setFixedPitch(True)
        font.setPointSize(10)
        self.setFont(font)
        self.setMarginsFont(font)

        # C/C++ lexer
        self.lexer = QsciLexerCPP(self, True)
        self.lexer.setDefaultFont(font)
        self.libraryAPIs = QsciAPIs(QsciLexerCPP(self, True))
        self.setLexer(self.lexer)
        self.SendScintilla(QsciScintilla.SCI_STYLESETFONT, 1, 'Courier')

        # Auto-indent
        self.setTabWidth(4)
        #self.setIndentationsUseTabs(False)
        self.setAutoIndent(True)

        # Current line visible with special background color
        self.setCaretLineVisible(True)
        self.setCaretLineBackgroundColor(QtGui.QColor("#ffe4e4"))

        # Enable brace matching
        self.setBraceMatching(QsciScintilla.SloppyBraceMatch)

        # Enable folding visual- use boxes
        self.setFolding(QsciScintilla.BoxedTreeFoldStyle)

        # show line numbers
        fontmetrics = QtGui.QFontMetrics(font)
        self.setMarginsFont(font)
        self.setMarginWidth(0, fontmetrics.width("00000") + 4)
        self.setMarginLineNumbers(0, True)
        self.setMarginsBackgroundColor(QtGui.QColor("#ccccee"))

        # not too small
        self.setMinimumSize(400, 200)

        # set the length of the string before the editor tries to auto-complete
        self.setAutoCompletionThreshold(3)
        # tell the editor we are using a QsciAPI for the auto-completion
        self.setAutoCompletionSource(QsciScintilla.AcsAPIs)
        # removed remaining right side characters from the current cursor
        self.setAutoCompletionReplaceWord(True)

        # "CTRL+Space" autocomplete
        self.shortcut_ctrl_space = QtGui.QShortcut(
            QtGui.QKeySequence("Ctrl+Space"), self)
        self.connect(self.shortcut_ctrl_space, QtCore.SIGNAL('activated()'),
                     self.autoCompleteFromAll)

        if fileName:
            self.curFile = fileName
            self.loadFile(fileName)
            self.isUntitled = False
        else:
            self.curFile = PROJECT_NONAME + USER_CODE_EXT
            self.setText(__default_content__)
            self.isUntitled = True

        self.updateApiKeywords()
        self.isModified = False
        self.connect(self, QtCore.SIGNAL('textChanged()'), self.onTextChanged)
Exemple #11
0
class CppEditor(QsciScintilla):
    '''
    classdocs
    '''
    def __init__(self, parent=None, fileName=None, readOnlyFiles=[]):
        '''
        Constructor
        '''
        super(CppEditor, self).__init__(parent)
        self.parent = parent
        self.roFiles = readOnlyFiles

        self.setAcceptDrops(False)  # drag&drop is on its parent

        # Set the default font
        font = QtGui.QFont()
        font.setFamily('Courier')
        font.setFixedPitch(True)
        font.setPointSize(10)
        self.setFont(font)
        self.setMarginsFont(font)

        # C/C++ lexer
        self.lexer = QsciLexerCPP(self, True)
        self.lexer.setDefaultFont(font)
        self.libraryAPIs = QsciAPIs(QsciLexerCPP(self, True))
        self.setLexer(self.lexer)
        self.SendScintilla(QsciScintilla.SCI_STYLESETFONT, 1, 'Courier')

        # Auto-indent
        self.setTabWidth(4)
        #self.setIndentationsUseTabs(False)
        self.setAutoIndent(True)

        # Current line visible with special background color
        self.setCaretLineVisible(True)
        self.setCaretLineBackgroundColor(QtGui.QColor("#ffe4e4"))

        # Enable brace matching
        self.setBraceMatching(QsciScintilla.SloppyBraceMatch)

        # Enable folding visual- use boxes
        self.setFolding(QsciScintilla.BoxedTreeFoldStyle)

        # show line numbers
        fontmetrics = QtGui.QFontMetrics(font)
        self.setMarginsFont(font)
        self.setMarginWidth(0, fontmetrics.width("00000") + 4)
        self.setMarginLineNumbers(0, True)
        self.setMarginsBackgroundColor(QtGui.QColor("#ccccee"))

        # not too small
        self.setMinimumSize(400, 200)

        # set the length of the string before the editor tries to auto-complete
        self.setAutoCompletionThreshold(3)
        # tell the editor we are using a QsciAPI for the auto-completion
        self.setAutoCompletionSource(QsciScintilla.AcsAPIs)
        # removed remaining right side characters from the current cursor
        self.setAutoCompletionReplaceWord(True)

        # "CTRL+Space" autocomplete
        self.shortcut_ctrl_space = QtGui.QShortcut(
            QtGui.QKeySequence("Ctrl+Space"), self)
        self.connect(self.shortcut_ctrl_space, QtCore.SIGNAL('activated()'),
                     self.autoCompleteFromAll)

        if fileName:
            self.curFile = fileName
            self.loadFile(fileName)
            self.isUntitled = False
        else:
            self.curFile = PROJECT_NONAME + USER_CODE_EXT
            self.setText(__default_content__)
            self.isUntitled = True

        self.updateApiKeywords()
        self.isModified = False
        self.connect(self, QtCore.SIGNAL('textChanged()'), self.onTextChanged)

    def onTextChanged(self):
        self.isModified = True
        self.parent.onChildContentChanged()

    def loadFile(self, fileName):
        qfile = QtCore.QFile(fileName)
        if not qfile.open(QtCore.QFile.ReadOnly | QtCore.QFile.Text):
            QtGui.QMessageBox.warning(
                self, PROJECT_ALIAS,
                "Cannot read file %s:\n%s." % (fileName, qfile.errorString()))
            return False

        ret = True
        try:
            # workaround for OS X QFile.readAll()
            f = open(qfile.fileName(), 'r')
            self.clear()
            for line in f.readlines():
                self.append(line)
        except:
            QtGui.QMessageBox.warning(self, PROJECT_ALIAS,
                                      "failed to read %s." % fileName)
            ret = False
        finally:
            f.close()

        qfile.close()
        return ret

    def saveFile(self, fileName):
        if str(fileName).find(' ') >= 0:
            QtGui.QMessageBox.warning(
                self, PROJECT_ALIAS,
                'File path "%s" contains space(s). Please save to a valid location.'
                % fileName)
            return None
        qfile = QtCore.QFile(fileName)
        if not qfile.open(QtCore.QFile.WriteOnly | QtCore.QFile.Text):
            QtGui.QMessageBox.warning(
                self, PROJECT_ALIAS,
                "Cannot write file %s:\n%s." % (fileName, qfile.errorString()))
            return None

        try:
            qfile.writeData(self.text())
        except:
            QtGui.QMessageBox.warning(self, PROJECT_ALIAS,
                                      "Failed to save %s." % fileName)
            qfile.close()
            return None

        qfile.close()
        self.curFile = fileName
        self.isUntitled = False
        self.isModified = False
        return fileName

    def saveAs(self):
        fileName = QtGui.QFileDialog.getSaveFileName(
            self, "Save As", self.curFile,
            PROJECT_ALIAS + " (*" + USER_CODE_EXT + ");;" +
            "C source (*.c);;C++ source (*.cpp);;Text File (*.txt);;All files (*.*)"
        )
        if not fileName:
            return None
        return self.saveFile(fileName)

    def save(self):
        f1 = os.path.abspath(self.curFile)
        for fname in self.roFiles:
            if f1 == os.path.abspath(fname):  # same file
                if QtGui.QMessageBox.question(self.parent, "Project is read-only",
                        "This project is marked as \"read-only\".\n" + \
                        "Please click \"Cancel\" and save this to another location.\n\n" + \
                        "Continue saving the current project anyway?", "OK", "Cancel"):
                    return None
                #return self.saveAs()
                return self.saveFile(self.curFile)
        if self.isUntitled:
            return self.saveAs()
        else:
            return self.saveFile(self.curFile)

    def currentFile(self):
        return self.curFile

    def modified(self):
        return self.isModified

    def updateApiKeywords(self):
        self.libraryAPIs.clear()
        self.apiKeywords = self.parent.getDefaultKeywords()
        headerfiles = []
        for line in range(self.lines()):
            txt = str(self.text(line)).strip()
            if txt.find('int') == 0:  # e.g. reached "int main()"
                break
            elif txt.find('#include') == 0:
                txt = ''.join(txt.split())
                temp = txt[len('#includes') - 1:]
                header = temp[1:-1]  # get the header file
                hfile = os.path.join('libraries', header[:-2], header)
                if os.path.isfile(hfile):
                    if not (hfile in headerfiles): headerfiles.append(hfile)
        if len(headerfiles):
            #print 'parsing: ', headerfiles
            self.apiKeywords += getLibraryKeywords(headerfiles)
        #self.apiKeywords = list(set(self.apiKeywords)) # remove duplicates
        for keyword in self.apiKeywords:
            self.libraryAPIs.add(keyword)
        self.libraryAPIs.prepare()
        self.lexer.setAPIs(self.libraryAPIs)

    def insertIncludeDirective(self, library=''):
        directive = '#include <' + library + '.h>\r\n'
        insert_pos = 0
        found_inc = False
        for line in range(self.lines()):
            txt = str(self.text(line)).strip()
            if txt.find('int') == 0:  # e.g. reached "int main()"
                insert_pos = line - 1
                break
            elif txt.find('#include') == 0:
                found_inc = True
            elif found_inc:
                insert_pos = line
                break
        if insert_pos < 0 or insert_pos >= self.lines():
            insert_pos = 0
        self.insertAt(directive, insert_pos, 0)
        self.updateApiKeywords()
Exemple #12
0
 def defaultEolFill(self, ix):
     for i in self.styles:
       if i.style() == ix:
         return i.eolFill()
     return QsciLexerCPP.defaultEolFill(self, ix)
Exemple #13
0
 def defaultPaper(self, ix):
     for i in self.styles:
       if i.style() == ix:
         return i.paper()
     return QsciLexerCPP.defaultPaper(self, ix)
Exemple #14
0
    def __init__(self, parent=None, fileName=None, readOnlyFiles=[]):
        '''
        Constructor
        '''
        super(CppEditor, self).__init__(parent)
        self.parent = parent
        self.roFiles = readOnlyFiles

        self.setAcceptDrops(False) # drag&drop is on its parent

        # Set the default font
        font = QtGui.QFont()
        font.setFamily('Courier')
        font.setFixedPitch(True)
        font.setPointSize(10)
        self.setFont(font)
        self.setMarginsFont(font)

        # C/C++ lexer
        self.lexer = QsciLexerCPP(self,  True)
        self.lexer.setDefaultFont(font)
        self.libraryAPIs = QsciAPIs(QsciLexerCPP(self,True))
        self.setLexer(self.lexer)
        self.SendScintilla(QsciScintilla.SCI_STYLESETFONT, 1, 'Courier')

        # Auto-indent
        self.setTabWidth(4)
        #self.setIndentationsUseTabs(False)
        self.setAutoIndent(True)

        # Current line visible with special background color
        self.setCaretLineVisible(True)
        self.setCaretLineBackgroundColor(QtGui.QColor("#ffe4e4"))

        # Enable brace matching
        self.setBraceMatching(QsciScintilla.SloppyBraceMatch)

        # Enable folding visual- use boxes
        self.setFolding(QsciScintilla.BoxedTreeFoldStyle)

        # show line numbers
        fontmetrics = QtGui.QFontMetrics(font)
        self.setMarginsFont(font)
        self.setMarginWidth(0, fontmetrics.width("00000") + 4)
        self.setMarginLineNumbers(0, True)
        self.setMarginsBackgroundColor(QtGui.QColor("#ccccee"))

        # not too small
        self.setMinimumSize(400, 200)

        # set the length of the string before the editor tries to auto-complete
        self.setAutoCompletionThreshold(3)
        # tell the editor we are using a QsciAPI for the auto-completion
        self.setAutoCompletionSource(QsciScintilla.AcsAPIs)
        # removed remaining right side characters from the current cursor
        self.setAutoCompletionReplaceWord(True)

        # "CTRL+Space" autocomplete
        self.shortcut_ctrl_space = QtGui.QShortcut(QtGui.QKeySequence("Ctrl+Space"), self)
        self.connect(self.shortcut_ctrl_space,
            QtCore.SIGNAL('activated()'), self.autoCompleteFromAll)

        if fileName:
            self.curFile = fileName
            self.loadFile(fileName)
            self.isUntitled = False
        else:
            self.curFile = PROJECT_NONAME + USER_CODE_EXT
            self.setText( __default_content__ )
            self.isUntitled = True

        self.updateApiKeywords()
        self.isModified = False
        self.connect(self, QtCore.SIGNAL('textChanged()'), self.onTextChanged )
Exemple #15
0
 def defaultColor(self, ix):
     for i in self.styles:
       if i.style() == ix:
         return i.color()
     return QsciLexerCPP.defaultColor(self, ix)
    def __init__(self, distributedObjects, filename, parent):
        ScintillaWrapper.__init__(self, parent)
        self.breakpointOverlays = {}

        filename = str(filename)
        self.distributedObjects = distributedObjects
        self.debugController = self.distributedObjects.debugController
        self.__bpModel = self.distributedObjects.breakpointModel
        self.tracepointController = self.distributedObjects.tracepointController
        self.signalProxy = self.distributedObjects.signalProxy
        self.filename = filename
        self.lastContextMenuLine = 0
        self.markerBp = QPixmap(":/markers/bp.png")
        self.markerBpDisabled = QPixmap(":/markers/bp_dis.png")
        self.markerTp = QPixmap(":/markers/tp.png")
        self.markerExec = QPixmap(":/markers/exec_pos.png")
        self.markerStack = QPixmap(":/markers/stack_pos.png")
        self.markerExecSignal = QPixmap(":/markers/exec_pos_signal.png")
        self.shown = False

        self.setToolTip("")
        self.setWhatsThis("")
        self.setMarginLineNumbers(self.MARGIN_NUMBERS, True)
        # set sensitivity
        self.setMarginSensitivity(self.MARGIN_NUMBERS, True)
        self.setMarginSensitivity(self.MARGIN_MARKER_BP, True)
        self.setMarginSensitivity(self.MARGIN_MARKER_TP, True)
        # define symbol
        self.markerDefine(self.markerBp, self.MARGIN_MARKER_BP)
        self.markerDefine(self.markerBpDisabled, self.MARGIN_MARKER_BP_DIS)
        self.markerDefine(self.markerTp, self.MARGIN_MARKER_TP)
        self.markerDefine(self.markerExec, self.MARGIN_MARKER_EXEC)
        self.markerDefine(self.markerStack, self.MARGIN_MARKER_STACK)
        self.markerDefine(self.markerExecSignal, self.MARGIN_MARKER_EXEC_SIGNAL)
        self.markerDefine(QsciScintilla.Background, self.MARKER_HIGHLIGHTED_LINE)

        # define width and mask to show margin
        self.setMarginWidth(self.MARGIN_MARKER_BP, 10)
        self.setMarginMarkerMask(self.MARGIN_MARKER_BP, 1 << self.MARGIN_MARKER_BP | 1 << self.MARGIN_MARKER_BP_DIS)
        self.setMarginWidth(self.MARGIN_MARKER_TP, 10)
        self.setMarginMarkerMask(self.MARGIN_MARKER_TP, 1 << self.MARGIN_MARKER_TP)
        self.setMarginWidth(self.MARGIN_MARKER_EXEC, 10)
        self.setMarginMarkerMask(self.MARGIN_MARKER_EXEC,
                1 << self.MARGIN_MARKER_EXEC |
                1 << self.MARGIN_MARKER_EXEC_SIGNAL |
                1 << self.MARGIN_MARKER_STACK)
        self.setMarginWidth(self.MARKER_HIGHLIGHTED_LINE, 0)
        self.setMarginMarkerMask(self.MARKER_HIGHLIGHTED_LINE, 1 << self.MARKER_HIGHLIGHTED_LINE)

        self.INDICATOR_TOOLTIP = self.indicatorDefine(self.BoxIndicator)
        self.setIndicatorDrawUnder(True, self.INDICATOR_TOOLTIP)

        self.setReadOnly(False)
        self.modificationChanged.connect(self.__setFileModified)

        self.SendScintilla(QsciScintilla.SCI_SETMOUSEDWELLTIME, 500)

        # override scintillas context menu with our own
        self.SendScintilla(QsciScintilla.SCI_USEPOPUP, 0)
        self.setContextMenuPolicy(Qt.CustomContextMenu)
        self.customContextMenuRequested.connect(self.showContextMenu)

        self.marginClicked.connect(self.onMarginClicked)
        self.SCN_DOUBLECLICK.connect(self.editDoubleClicked)
        self.dwellStart.connect(self.onDwellStart)
        self.dwellEnd.connect(self.onDwellEnd)

        self.__bpModel.rowsInserted.connect(self.breakpointsInserted)
        # don't connect to rowsRemoved here since the breakpoint is already gone
        # from the model when it's emitted
        self.__bpModel.rowsAboutToBeRemoved.connect(self.breakpointsRemoved)
        self.__bpModel.dataChanged.connect(self.breakpointsModified)
        _model = self.tracepointController.model()
        _model.rowsInserted.connect(self.getTracepointsFromModel)
        _model.rowsRemoved.connect(self.getTracepointsFromModel)

        act = self.distributedObjects.actions
        act.ToggleTrace.triggered.connect(self.toggleTracepoint)

        self.__allowToolTip = True
        self.__enableToolTip(True)

        self.__popupMenu = None

        self.__disAsmStyle = QsciStyle()

        self.__fileWatcher = QFileSystemWatcher([self.filename])
        self.__fileWatcher.fileChanged.connect(self.__fileChanged)

        # this timer is used for a workaround: QFileSystemWatcher will sometimes
        # report a change multiple times; therefore, in self.__fileChanged, we
        # simply start the timer on a notification and discard all notifications
        # while the timer is running
        self.__fileChangedTimer = QTimer()
        self.__fileChangedTimer.setSingleShot(True)
        self.__fileChangedTimer.setInterval(100)

        ScintillaWrapper.init(self, distributedObjects)
        self.setLexer(QsciLexerCPP())

        self.openFile()
	def __init__(self):
		QsciLexerCPP.__init__(self)
		print "LexerArduino"
Exemple #18
0
 def defaultColor(self, style):
     '''Returns the foreground colour of the text for style number style'''
     color = self.lexer.get_default_color(style, self.description(style))
     if color != 'not':
         return color
     return QsciLexerCPP.defaultColor(self, style)
 def __init__(self):
     QsciLexerCPP.__init__(self)
     print "LexerArduino"
Exemple #20
0
 def defaultFont(self, ix):
     for i in self.styles:
       if i.style() == ix:
         return i.font()
     return QsciLexerCPP.defaultFont(self, ix)
Exemple #21
0
from PyQt4 import QtGui,QtCore
from PyQt4.Qsci import QsciScintilla, QsciLexerCPP
import sys

app = QtGui.QApplication(sys.argv)
window = QtGui.QWidget()

scint = QsciScintilla(window)
lex = QsciLexerCPP(window,False)
scint.setLexer(lex)
window.show()

sys.exit( app.exec_() )
Exemple #22
0
class CppEditor(QsciScintilla):
    '''
    classdocs
    '''
    def __init__(self, parent=None, fileName=None, readOnlyFiles=[]):
        '''
        Constructor
        '''
        super(CppEditor, self).__init__(parent)
        self.parent = parent
        self.roFiles = readOnlyFiles

        self.setAcceptDrops(False) # drag&drop is on its parent

        # Set the default font
        font = QtGui.QFont()
        font.setFamily('Courier')
        font.setFixedPitch(True)
        font.setPointSize(10)
        self.setFont(font)
        self.setMarginsFont(font)

        # C/C++ lexer
        self.lexer = QsciLexerCPP(self,  True)
        self.lexer.setDefaultFont(font)
        self.libraryAPIs = QsciAPIs(QsciLexerCPP(self,True))
        self.setLexer(self.lexer)
        self.SendScintilla(QsciScintilla.SCI_STYLESETFONT, 1, 'Courier')

        # Auto-indent
        self.setTabWidth(4)
        #self.setIndentationsUseTabs(False)
        self.setAutoIndent(True)

        # Current line visible with special background color
        self.setCaretLineVisible(True)
        self.setCaretLineBackgroundColor(QtGui.QColor("#ffe4e4"))

        # Enable brace matching
        self.setBraceMatching(QsciScintilla.SloppyBraceMatch)

        # Enable folding visual- use boxes
        self.setFolding(QsciScintilla.BoxedTreeFoldStyle)

        # show line numbers
        fontmetrics = QtGui.QFontMetrics(font)
        self.setMarginsFont(font)
        self.setMarginWidth(0, fontmetrics.width("00000") + 4)
        self.setMarginLineNumbers(0, True)
        self.setMarginsBackgroundColor(QtGui.QColor("#ccccee"))

        # not too small
        self.setMinimumSize(400, 200)

        # set the length of the string before the editor tries to auto-complete
        self.setAutoCompletionThreshold(3)
        # tell the editor we are using a QsciAPI for the auto-completion
        self.setAutoCompletionSource(QsciScintilla.AcsAPIs)
        # removed remaining right side characters from the current cursor
        self.setAutoCompletionReplaceWord(True)

        # "CTRL+Space" autocomplete
        self.shortcut_ctrl_space = QtGui.QShortcut(QtGui.QKeySequence("Ctrl+Space"), self)
        self.connect(self.shortcut_ctrl_space,
            QtCore.SIGNAL('activated()'), self.autoCompleteFromAll)

        if fileName:
            self.curFile = fileName
            self.loadFile(fileName)
            self.isUntitled = False
        else:
            self.curFile = PROJECT_NONAME + USER_CODE_EXT
            self.setText( __default_content__ )
            self.isUntitled = True

        self.updateApiKeywords()
        self.isModified = False
        self.connect(self, QtCore.SIGNAL('textChanged()'), self.onTextChanged )

    def onTextChanged(self):
        self.isModified = True
        self.parent.onChildContentChanged()

    def loadFile(self, fileName):
        qfile = QtCore.QFile(fileName)
        if not qfile.open(QtCore.QFile.ReadOnly | QtCore.QFile.Text):
            QtGui.QMessageBox.warning(self, PROJECT_ALIAS,
                    "Cannot read file %s:\n%s." % (fileName, qfile.errorString()))
            return False

        ret = True
        try:
            # workaround for OS X QFile.readAll()
            f = open(qfile.fileName(), 'r')
            self.clear()
            for line in f.readlines():
                self.append(line)
        except:
            QtGui.QMessageBox.warning(self, PROJECT_ALIAS,
                    "failed to read %s." % fileName )
            ret = False
        finally:
            f.close()

        qfile.close()
        return ret

    def saveFile(self, fileName):
        if str(fileName).find(' ')>=0:
            QtGui.QMessageBox.warning(self, PROJECT_ALIAS,
                    'File path "%s" contains space(s). Please save to a valid location.'%fileName)
            return None
        qfile = QtCore.QFile(fileName)
        if not qfile.open(QtCore.QFile.WriteOnly | QtCore.QFile.Text):
            QtGui.QMessageBox.warning(self, PROJECT_ALIAS,
                    "Cannot write file %s:\n%s." % (fileName, qfile.errorString()))
            return None

        try:
            qfile.writeData(self.text())
        except:
            QtGui.QMessageBox.warning(self, PROJECT_ALIAS,
                    "Failed to save %s." % fileName )
            qfile.close()
            return None

        qfile.close()
        self.curFile = fileName
        self.isUntitled = False
        self.isModified = False
        return fileName

    def saveAs(self):
        fileName = QtGui.QFileDialog.getSaveFileName(self, "Save As",
                self.curFile, PROJECT_ALIAS + " (*" + USER_CODE_EXT + ");;" +
                    "C source (*.c);;C++ source (*.cpp);;Text File (*.txt);;All files (*.*)" )
        if not fileName:
            return None
        return self.saveFile(fileName)

    def save(self):
        f1 = os.path.abspath(self.curFile)
        for fname in self.roFiles:
            if f1 == os.path.abspath(fname): # same file
                if QtGui.QMessageBox.question(self.parent, "Project is read-only",
                        "This project is marked as \"read-only\".\n" + \
                        "Please click \"Cancel\" and save this to another location.\n\n" + \
                        "Continue saving the current project anyway?", "OK", "Cancel"):
                    return None
                #return self.saveAs()
                return self.saveFile(self.curFile)
        if self.isUntitled:
            return self.saveAs()
        else:
            return self.saveFile(self.curFile)

    def currentFile(self):
        return self.curFile

    def modified(self):
        return self.isModified

    def updateApiKeywords(self):
        self.libraryAPIs.clear()
        self.apiKeywords = self.parent.getDefaultKeywords()
        headerfiles = []
        for line in range(self.lines()):
            txt = str(self.text(line)).strip()
            if txt.find('int') == 0: # e.g. reached "int main()"
                break
            elif txt.find('#include') == 0:
                txt = ''.join(txt.split())
                temp = txt[len('#includes')-1 : ]
                header = temp[1:-1] # get the header file
                hfile = os.path.join('libraries', header[:-2], header)
                if os.path.isfile(hfile):
                    if not (hfile in headerfiles): headerfiles.append( hfile )
        if len( headerfiles ):
            #print 'parsing: ', headerfiles
            self.apiKeywords += getLibraryKeywords( headerfiles )
        #self.apiKeywords = list(set(self.apiKeywords)) # remove duplicates
        for keyword in self.apiKeywords:
            self.libraryAPIs.add( keyword )
        self.libraryAPIs.prepare()
        self.lexer.setAPIs(self.libraryAPIs)

    def insertIncludeDirective(self, library=''):
        directive =  '#include <' + library + '.h>\r\n'
        insert_pos = 0
        found_inc = False
        for line in range(self.lines()):
            txt = str(self.text(line)).strip()
            if txt.find('int') == 0: # e.g. reached "int main()"
                insert_pos = line - 1
                break
            elif txt.find('#include') == 0:
                found_inc = True
            elif found_inc:
                insert_pos = line
                break
        if insert_pos < 0 or insert_pos >= self.lines():
            insert_pos = 0
        self.insertAt(directive, insert_pos, 0)
        self.updateApiKeywords()