class APIs(QObject): """ Class implementing an API storage entity. @signal apiPreparationFinished() emitted after the API preparation has finished @signal apiPreparationCancelled() emitted after the API preparation has been cancelled @signal apiPreparationStarted() emitted after the API preparation has started """ apiPreparationFinished = pyqtSignal() apiPreparationCancelled = pyqtSignal() apiPreparationStarted = pyqtSignal() def __init__(self, language, forPreparation=False, parent=None): """ Constructor @param language language of the APIs object (string) @param forPreparation flag indicating this object is just needed for a preparation process (boolean) @param parent reference to the parent object (QObject) """ super(APIs, self).__init__(parent) self.setObjectName("APIs_{0}".format(language)) self.__inPreparation = False self.__language = language self.__forPreparation = forPreparation self.__lexer = Lexers.getLexer(self.__language) self.__apifiles = Preferences.getEditorAPI(self.__language) self.__apifiles.sort() if self.__lexer is None: self.__apis = None else: self.__apis = QsciAPIs(self.__lexer) self.__apis.apiPreparationFinished.connect( self.__apiPreparationFinished) self.__apis.apiPreparationCancelled.connect( self.__apiPreparationCancelled) self.__apis.apiPreparationStarted.connect( self.__apiPreparationStarted) self.__loadAPIs() def __loadAPIs(self): """ Private method to load the APIs. """ if self.__apis.isPrepared(): # load a prepared API file if not self.__forPreparation and \ Preferences.getEditor("AutoPrepareAPIs"): self.prepareAPIs() self.__apis.loadPrepared() else: # load the raw files and prepare the API file if not self.__forPreparation and \ Preferences.getEditor("AutoPrepareAPIs"): self.prepareAPIs(ondemand=True) def reloadAPIs(self): """ Public method to reload the API information. """ if not self.__forPreparation and \ Preferences.getEditor("AutoPrepareAPIs"): self.prepareAPIs() self.__loadAPIs() def getQsciAPIs(self): """ Public method to get a reference to QsciAPIs object. @return reference to the QsciAPIs object (QsciAPIs) """ if not self.__forPreparation and \ Preferences.getEditor("AutoPrepareAPIs"): self.prepareAPIs() return self.__apis def isEmpty(self): """ Public method to check, if the object has API files configured. @return flag indicating no API files have been configured (boolean) """ return len(self.__apifiles) == 0 def __apiPreparationFinished(self): """ Private method called to save an API, after it has been prepared. """ self.__apis.savePrepared() self.__inPreparation = False self.apiPreparationFinished.emit() def __apiPreparationCancelled(self): """ Private method called, after the API preparation process has been cancelled. """ self.__inPreparation = False self.apiPreparationCancelled.emit() def __apiPreparationStarted(self): """ Private method called, when the API preparation process started. """ self.__inPreparation = True self.apiPreparationStarted.emit() def prepareAPIs(self, ondemand=False, rawList=None): """ Public method to prepare the APIs if necessary. @keyparam ondemand flag indicating a requested preparation (boolean) @keyparam rawList list of raw API files (list of strings) """ if self.__apis is None or self.__inPreparation: return needsPreparation = False if ondemand: needsPreparation = True else: # check, if a new preparation is necessary preparedAPIs = self.__defaultPreparedName() if preparedAPIs: preparedAPIsInfo = QFileInfo(preparedAPIs) if not preparedAPIsInfo.exists(): needsPreparation = True else: preparedAPIsTime = preparedAPIsInfo.lastModified() apifiles = sorted( Preferences.getEditorAPI(self.__language)) if self.__apifiles != apifiles: needsPreparation = True for apifile in apifiles: if QFileInfo(apifile).lastModified() > \ preparedAPIsTime: needsPreparation = True break if needsPreparation: # do the preparation self.__apis.clear() if rawList: apifiles = rawList else: apifiles = Preferences.getEditorAPI(self.__language) for apifile in apifiles: self.__apis.load(apifile) self.__apis.prepare() self.__apifiles = apifiles def cancelPreparation(self): """ Public slot to cancel the APIs preparation. """ self.__apis and self.__apis.cancelPreparation() def installedAPIFiles(self): """ Public method to get a list of installed API files. @return list of installed API files (list of strings) """ if self.__apis is not None: if Globals.isWindowsPlatform(): qsciPath = os.path.join( Globals.getPyQt5ModulesDirectory(), "qsci") if os.path.exists(qsciPath): # it's the installer if self.__lexer.lexerName() is not None: apidir = os.path.join(qsciPath, "api", self.__lexer.lexerName()) fnames = [] filist = QDir(apidir).entryInfoList( ["*.api"], QDir.Files, QDir.IgnoreCase) for fi in filist: fnames.append(fi.absoluteFilePath()) return fnames else: return [] return self.__apis.installedAPIFiles() else: return [] def __defaultPreparedName(self): """ Private method returning the default name of a prepared API file. @return complete filename for the Prepared APIs file (string) """ if self.__apis is not None: return self.__apis.defaultPreparedName() else: return ""
class APIs(QObject): """ Class implementing an API storage entity. @signal apiPreparationFinished() emitted after the API preparation has finished @signal apiPreparationCancelled() emitted after the API preparation has been cancelled @signal apiPreparationStarted() emitted after the API preparation has started """ apiPreparationFinished = pyqtSignal() apiPreparationCancelled = pyqtSignal() apiPreparationStarted = pyqtSignal() def __init__(self, language, projectType="", forPreparation=False, parent=None): """ Constructor @param language language of the APIs object @type str @param projectType type of the project @type str @param forPreparation flag indicating this object is just needed for a preparation process @type bool @param parent reference to the parent object @type QObject """ super(APIs, self).__init__(parent) if projectType: self.setObjectName("APIs_{0}_{1}".format(language, projectType)) else: self.setObjectName("APIs_{0}".format(language)) self.__inPreparation = False self.__language = language self.__projectType = projectType self.__forPreparation = forPreparation self.__lexer = Lexers.getLexer(self.__language) self.__apifiles = Preferences.getEditorAPI(self.__language, self.__projectType) self.__apifiles.sort() if self.__lexer is None: self.__apis = None else: self.__apis = QsciAPIs(self.__lexer) self.__apis.apiPreparationFinished.connect( self.__apiPreparationFinished) self.__apis.apiPreparationCancelled.connect( self.__apiPreparationCancelled) self.__apis.apiPreparationStarted.connect( self.__apiPreparationStarted) self.__loadAPIs() def __loadAPIs(self): """ Private method to load the APIs. """ if self.__apis.isPrepared(): # load a prepared API file if (not self.__forPreparation and Preferences.getEditor("AutoPrepareAPIs")): self.prepareAPIs() self.__apis.loadPrepared(self.__preparedName()) else: # load the raw files and prepare the API file if (not self.__forPreparation and Preferences.getEditor("AutoPrepareAPIs")): self.prepareAPIs(ondemand=True) def reloadAPIs(self): """ Public method to reload the API information. """ if (not self.__forPreparation and Preferences.getEditor("AutoPrepareAPIs")): self.prepareAPIs() self.__loadAPIs() def getQsciAPIs(self): """ Public method to get a reference to QsciAPIs object. @return reference to the QsciAPIs object (QsciAPIs) """ if (not self.__forPreparation and Preferences.getEditor("AutoPrepareAPIs")): self.prepareAPIs() return self.__apis def isEmpty(self): """ Public method to check, if the object has API files configured. @return flag indicating no API files have been configured (boolean) """ return len(self.__apifiles) == 0 def __apiPreparationFinished(self): """ Private method called to save an API, after it has been prepared. """ self.__apis.savePrepared(self.__preparedName()) self.__inPreparation = False self.apiPreparationFinished.emit() def __apiPreparationCancelled(self): """ Private method called, after the API preparation process has been cancelled. """ self.__inPreparation = False self.apiPreparationCancelled.emit() def __apiPreparationStarted(self): """ Private method called, when the API preparation process started. """ self.__inPreparation = True self.apiPreparationStarted.emit() def prepareAPIs(self, ondemand=False, rawList=None): """ Public method to prepare the APIs if necessary. @keyparam ondemand flag indicating a requested preparation (boolean) @keyparam rawList list of raw API files (list of strings) """ if self.__apis is None or self.__inPreparation: return needsPreparation = False if ondemand: needsPreparation = True else: # check, if a new preparation is necessary preparedAPIs = self.__preparedName() if preparedAPIs: preparedAPIsInfo = QFileInfo(preparedAPIs) if not preparedAPIsInfo.exists(): needsPreparation = True else: preparedAPIsTime = preparedAPIsInfo.lastModified() apifiles = sorted( Preferences.getEditorAPI(self.__language, self.__projectType)) if self.__apifiles != apifiles: needsPreparation = True for apifile in apifiles: if (QFileInfo(apifile).lastModified() > preparedAPIsTime): needsPreparation = True break if needsPreparation: # do the preparation self.__apis.clear() if rawList: apifiles = rawList else: apifiles = Preferences.getEditorAPI(self.__language, self.__projectType) for apifile in apifiles: self.__apis.load(apifile) self.__apis.prepare() self.__apifiles = apifiles def cancelPreparation(self): """ Public slot to cancel the APIs preparation. """ self.__apis and self.__apis.cancelPreparation() def installedAPIFiles(self): """ Public method to get a list of installed API files. @return list of installed API files (list of strings) """ if self.__apis is not None: if Globals.isWindowsPlatform(): qsciPath = os.path.join(Globals.getPyQt5ModulesDirectory(), "qsci") if os.path.exists(qsciPath): # it's the installer if self.__lexer.lexerName() is not None: apidir = os.path.join(qsciPath, "api", self.__lexer.lexerName()) fnames = [] filist = QDir(apidir).entryInfoList(["*.api"], QDir.Files, QDir.IgnoreCase) for fi in filist: fnames.append(fi.absoluteFilePath()) return fnames else: return [] return self.__apis.installedAPIFiles() else: return [] def __preparedName(self): """ Private method returning the default name of a prepared API file. @return complete filename for the Prepared APIs file (string) """ apisDir = os.path.join(Globals.getConfigDir(), "APIs") if self.__apis is not None: if self.__projectType: filename = "{0}_{1}.pap".format(self.__language, self.__projectType) else: filename = "{0}.pap".format(self.__language) return os.path.join(apisDir, filename) else: return ""
def _setup_editor(self): # set default editor settings self.editor.setFont(DEFAULT_FONT) self.editor.setMarginsFont(LINENO_FONT) self.editor.setBraceMatching(QsciScintilla.SloppyBraceMatch) self.editor.setCaretLineVisible(True) self.editor.setCaretForegroundColor(QColor('#000000')) self.editor.setCaretLineBackgroundColor(QColor('#c4e8fd')) self.editor.setAutoIndent(True) self.editor.setTabIndents(True) # tab width self.editor.setTabWidth(4) # line numbers (margin 0) self.editor.setMarginLineNumbers(0, True) self.editor.setMarginWidth(0, '00000') # hide symbol margin self.editor.setMarginWidth(1, 0) # folding self.editor.setFolding(1) # indentation guides self.editor.setIndentationGuides(True) # wrap mode wrap_lines = False self.editor.setWrapMode(wrap_lines) if wrap_lines: # remove horizontal scrollBar self.editor.SendScintilla(SCI.SCI_SETHSCROLLBAR, 0, 0) lexer = QsciLexerPython(self) # apply default settings to lexer lexer.setDefaultFont(DEFAULT_FONT) lexer.setFont(DEFAULT_FONT) # margins lexer.setPaper(MARGIN_BGCOLOR, SCI.STYLE_LINENUMBER) lexer.setColor(MARGIN_COLOR, SCI.STYLE_LINENUMBER) lexer.setFont(DEFAULT_FONT, SCI.STYLE_LINENUMBER) # assign the lexer self.editor.setLexer(lexer) self.editor.SendScintilla(SCI.SCI_COLOURISE, 0, -1) # margins self.editor.setMarginsBackgroundColor(MARGIN_BGCOLOR) self.editor.setMarginsForegroundColor(MARGIN_COLOR) self.editor.setMarginsFont(LINENO_FONT) # folding self.editor.setFolding(FOLDING) self.editor.SendScintilla(SCI.SCI_SETMARGINWIDTHN, FOLD_MARGIN_NUM, FOLD_MARGIN_WIDTH) # set fold margin colors self.editor.SendScintilla(SCI.SCI_SETFOLDMARGINCOLOUR, True, Main._color_to_bgr_int(FOLD_MARGIN_COLOR)) self.editor.SendScintilla(SCI.SCI_SETFOLDMARGINHICOLOUR, True, Main._color_to_bgr_int(FOLD_MARGIN_HICOLOR)) # create and configure the breakpoint column self.editor.setMarginWidth(self.__symbol_margin_num, 17) self.editor.markerDefine(BREAKPOINT_SYMBOL, self.__breakpoint_marker_num) self.editor.setMarginMarkerMask(self.__symbol_margin_num, self.__breakpoint_marker_mask) self.editor.setMarkerBackgroundColor(BREAKPOINT_COLOR, self.__breakpoint_marker_num) # make breakpoint margin clickable self.editor.setMarginSensitivity(self.__symbol_margin_num, True) # add new callback for breakpoints self.editor.marginClicked.connect(self._slot_margin_clicked) # setup active line marker self.editor.markerDefine(ACTIVE_LINE_SYMBOL, self.__active_line_marker_num) self.editor.setMarkerForegroundColor(ACTIVE_LINE_COLOR, self.__active_line_marker_num) self.editor.setMarkerBackgroundColor(ACTIVE_LINE_COLOR, self.__active_line_marker_num) # connect signals self.editor.textChanged.connect(self._slot_text_changed) self.editor.modificationChanged.connect( self._slot_editor_modification_changed) self.editor.SCN_URIDROPPED.connect(self._slot_file_dropped) self.editor.copyAvailable.connect(self.actionCut.setEnabled) self.editor.copyAvailable.connect(self.actionCopy.setEnabled) self.editor.selectionChanged.connect( lambda: self.actionDelete.setEnabled(self.editor.hasSelectedText() )) self.editor.selectionChanged.connect( lambda: self.actionSelectAll.setEnabled(self.editor. hasSelectedText())) # autocomplete if API_FILE is not None: apis = QsciAPIs(self.editor.lexer()) apis.loadPrepared(API_FILE) self.editor.setAutoCompletionThreshold(3) # The source is any installed APIs. self.editor.setAutoCompletionSource(QsciScintilla.AcsAPIs)