def _install(self): """Install the plugin to the core """ if self._installed: return self._schemeMenu = core.actionManager().addMenu("mScheme", "MIT Scheme") self._evalAction = core.actionManager().addAction("mScheme/aEval", "Eval. selection/Save and eval.") self._evalAction.setStatusTip("Evaluate selection. If nothing is selected - save and evaluate whole file") self._evalAction.setShortcut("Ctrl+E") self._evalAction.triggered.connect(self._onEvalTriggered) self._breakAction = core.actionManager().addAction("mScheme/aBreak", "Stop the interpreter") self._breakAction.setStatusTip("Use it as a restart action.") self._breakAction.setShortcut("Pause") self._breakAction.triggered.connect(self._onBreakTriggered) self._breakAction.setEnabled(False) self._activeInterpreterPath = core.config()["Modes"]["Scheme"]["InterpreterPath"] from mitscheme import MitScheme self._mitScheme = MitScheme(self._activeInterpreterPath) self._mitScheme.processIsRunningChanged.connect(lambda isRunning: self._breakAction.setEnabled(isRunning)) from mitscheme import MitSchemeDock self._dock = MitSchemeDock(self._mitScheme.widget()) core.mainWindow().addDockWidget(Qt.BottomDockWidgetArea, self._dock) self._dock.hide() self._installed = True
def addAction(self, path, action, icon=QIcon(), shortcut=None): """Add new action to the menu. Returns created QAction object. ``action`` might be string text or QAction instance. """ subPath = self._parentPath(path) parentAction = self.action(subPath) if parentAction is None: assert False, "Menu path not found: " + subPath if isinstance(action, str): action = QAction(icon, action, parentAction) else: action.setParent(parentAction) if shortcut is not None: action.setShortcut(shortcut) parentAction.menu().addAction(action) self._pathToAction[path] = action action.path = path action.changed.connect(self._onActionChanged) """ On Ubuntu 14.04 keyboard shortcuts doesn't work without this line http://stackoverflow.com/questions/23916623/ qt5-doesnt-recognised-shortcuts-unless-actions-are-added-to-a-toolbar """ core.mainWindow().addAction(action) self.actionInserted.emit(action) return action
def _convertIndentation(self): """Try to fix indentation mode of the file, if there are mix of different indentation modes (tabs and spaces) """ # get original text originalText = self.qscintilla.text() # all modifications must believe as only one action self.qscintilla.beginUndoAction() # get indent width indentWidth = self.qscintilla.indentationWidth() if indentWidth == 0: indentWidth = self.qscintilla.tabWidth() # iterate each line for i in range(self.qscintilla.lines()): # get current line indent width lineIndent = self.qscintilla.indentation(i) # remove indentation self.qscintilla.setIndentation(i, 0) # restore it with possible troncate indentation self.qscintilla.setIndentation(i, lineIndent) # end global undo action self.qscintilla.endUndoAction() # compare original and newer text if originalText == self.qscintilla.text(): # clear undo buffer self.qscintilla.SendScintilla(QsciScintilla.SCI_EMPTYUNDOBUFFER) # set unmodified self._setModified(False) else: core.mainWindow().appendMessage('Indentation converted. You can Undo the changes', 5000)
def test_1(self): """ File is checked after opened """ doc = self.createFile("te:st .py", "asdf\n\n") self.waitUntilPassed( 2000, lambda: self.assertEqual( doc.qutepart.lintMarks, {0: ("e", "F821 undefined name 'asdf'"), 1: ("w", "W391 blank line at end of file")}, ), ) self.assertEqual(core.mainWindow().statusBar().currentMessage(), "F821 undefined name 'asdf'") doc.qutepart.cursorPosition = (1, 0) self.assertEqual(core.mainWindow().statusBar().currentMessage(), "W391 blank line at end of file") doc.qutepart.cursorPosition = (0, 1) self.assertEqual(core.mainWindow().statusBar().currentMessage(), "F821 undefined name 'asdf'") doc.qutepart.text = "def main()\n return 7" self.assertEqual(doc.qutepart.lintMarks, {}) self.assertEqual(core.mainWindow().statusBar().currentMessage(), "") doc.saveFile() self.waitUntilPassed( 2000, lambda: self.assertEqual( doc.qutepart.lintMarks, {0: ("e", "E901 SyntaxError: invalid syntax"), 1: ("w", "E113 unexpected indentation")}, ), )
def _openSingleFile(self, filePath): """Open 1 file. Helper method, used by openFile() and openFiles() """ # Close 'untitled' if len(self.documents()) == 1 and \ self.documents()[0].fileName() is None and \ not self.documents()[0].filePath() and \ not self.documents()[0].qutepart.text and \ not self.documents()[0].qutepart.document().isModified(): self.closeDocument(self.documents()[0]) # check if file is already opened alreadyOpenedDocument = self.findDocumentForPath(filePath) if alreadyOpenedDocument is not None: self.setCurrentDocument( alreadyOpenedDocument ) return alreadyOpenedDocument # open file try: document = Document(self, filePath) except IOError as ex: QMessageBox.critical(None, self.tr("Failed to open file"), unicode(str(ex), 'utf8')) return None self._handleDocument( document ) if not os.access(filePath, os.W_OK): core.mainWindow().appendMessage( \ self.tr( "File '%s' is not writable" % filePath), 4000) # todo fix return document
def _onToggleExecutable(self): executable = self._isCurrentFileExecutable() assert executable is not None, 'aToggleExecutable must have been disabled' filePath = core.workspace().currentDocument().filePath() try: st = os.stat(filePath) except (IOError, OSError) as ex: QMessageBox.critical( core.mainWindow(), 'Failed to change executable mode', 'Failed to get current file mode: %s' % str(ex)) return if executable: newMode = st.st_mode & (~self.EXECUTABLE_FLAGS) else: newMode = st.st_mode | self.EXECUTABLE_FLAGS try: os.chmod(filePath, newMode) except (IOError, OSError) as ex: QMessageBox.critical( core.mainWindow(), 'Failed to change executable mode', 'Failed to set current file mode: %s' % str(ex)) return
def __init__(self, plugin): QFrame.__init__(self, core.workspace()) self._mode = None self.plugin = plugin from PyQt4 import uic # lazy import for better startup performance uic.loadUi(os.path.join(os.path.dirname(__file__), "SearchWidget.ui"), self) self.cbSearch.setCompleter(None) self.cbReplace.setCompleter(None) self.cbMask.setCompleter(None) self.fsModel = QDirModel(self.cbPath.lineEdit()) self.fsModel.setFilter(QDir.AllDirs | QDir.NoDotAndDotDot) self.cbPath.lineEdit().setCompleter(QCompleter(self.fsModel, self.cbPath.lineEdit())) # TODO QDirModel is deprecated but QCompleter does not yet handle # QFileSystemodel - please update when possible.""" self.cbSearch.setCompleter(None) self.pbSearchStop.setVisible(False) self.pbReplaceCheckedStop.setVisible(False) self._progress = QProgressBar(self) self._progress.setAlignment(Qt.AlignCenter) self._progress.setToolTip(self.tr("Search in progress...")) self._progress.setMaximumSize(QSize(80, 16)) core.mainWindow().statusBar().insertPermanentWidget(1, self._progress) self._progress.setVisible(False) # cd up action self.tbCdUp = QToolButton(self.cbPath.lineEdit()) self.tbCdUp.setIcon(QIcon(":/enkiicons/go-up.png")) self.tbCdUp.setCursor(Qt.ArrowCursor) self.tbCdUp.installEventFilter(self) # for drawing button self.cbSearch.installEventFilter(self) # for catching Tab and Shift+Tab self.cbReplace.installEventFilter(self) # for catching Tab and Shift+Tab self.cbPath.installEventFilter(self) # for catching Tab and Shift+Tab self.cbMask.installEventFilter(self) # for catching Tab and Shift+Tab self._closeShortcut = QShortcut(QKeySequence("Esc"), self) self._closeShortcut.setContext(Qt.WidgetWithChildrenShortcut) self._closeShortcut.activated.connect(self.hide) # connections self.cbSearch.lineEdit().textChanged.connect(self._onSearchRegExpChanged) self.cbSearch.lineEdit().returnPressed.connect(self._onReturnPressed) self.cbReplace.lineEdit().returnPressed.connect(self._onReturnPressed) self.cbPath.lineEdit().returnPressed.connect(self._onReturnPressed) self.cbMask.lineEdit().returnPressed.connect(self._onReturnPressed) self.cbRegularExpression.stateChanged.connect(self._onSearchRegExpChanged) self.cbCaseSensitive.stateChanged.connect(self._onSearchRegExpChanged) self.tbCdUp.clicked.connect(self._onCdUpPressed) core.mainWindow().hideAllWindows.connect(self.hide) core.workspace().currentDocumentChanged.connect( lambda old, new: self.setVisible(self.isVisible() and new is not None) )
def _createSearchWidget(self): """ Create search widget. Called only when user requested it first time """ from . import searchwidget self._widget = searchwidget.SearchWidget(self) self._widget.searchInDirectoryStartPressed.connect( self._onSearchInDirectoryStartPressed) self._widget.searchInDirectoryStopPressed.connect( self._onSearchInDirectoryStopPressed) self._widget.replaceCheckedStartPressed.connect( self._onReplaceCheckedStartPressed) self._widget.replaceCheckedStopPressed.connect( self._onReplaceCheckedStopPressed) self._widget.visibilityChanged.connect( self._updateSearchWidgetFoundItemsHighlighting) self._widget.searchRegExpChanged.connect(self._updateFileActionsState) self._widget.searchRegExpChanged.connect(self._onRegExpChanged) self._widget.searchRegExpChanged.connect( self._updateSearchWidgetFoundItemsHighlighting) self._widget.searchNext.connect(self._onSearchNext) self._widget.searchPrevious.connect(self._onSearchPrevious) self._widget.replaceFileOne.connect(self._onReplaceFileOne) self._widget.replaceFileAll.connect(self._onReplaceFileAll) core.workspace().currentDocumentChanged.connect( self._updateFileActionsState) # always disabled, if no widget core.workspace().textChanged.connect( self._updateSearchWidgetFoundItemsHighlighting) core.mainWindow().centralLayout().addWidget(self._widget) self._widget.setVisible(False) self._updateFileActionsState()
def _onRename(self): """Handler for File->File System->Rename""" document = core.workspace().currentDocument() if document.qutepart.document().isModified() or \ document.isExternallyModified() or \ document.isExternallyRemoved() or \ document.isNeverSaved(): QMessageBox.warning(core.mainWindow(), 'Rename file', 'Save the file before renaming') return newPath, ok = QInputDialog.getText(core.mainWindow(), 'Rename file', 'New file name', text=document.filePath()) if not ok: return if newPath == document.filePath(): return if newPath == '/dev/null': try: os.remove(document.filePath()) except (OSError, IOError) as ex: QMessageBox.critical(core.mainWindow(), 'Not this time', 'The OS thinks it needs the file') else: core.workspace().closeDocument(document) else: try: os.rename(document.filePath(), newPath) except (OSError, IOError) as ex: QMessageBox.critical(core.mainWindow(), 'Failed to rename file', str(ex)) else: document.setFilePath(newPath) document.saveFile()
def _removeDock(self): """Remove dock from GUI """ self._wasVisible = self._dock.isVisible() core.actionManager().removeAction("mView/aPreview") core.mainWindow().removeDockWidget(self._dock) self._dockInstalled = False
def test_1(self): """ File is checked after opened """ doc = self.createFile('te:st .py', 'asdf\n\n') self.waitUntilPassed( 2000, lambda: self.assertEqual( doc.qutepart.lintMarks, { 0: ('e', "F821 undefined name 'asdf'"), 1: ('w', 'W391 blank line at end of file') })) self.assertEqual(core.mainWindow().statusBar().currentMessage(), "F821 undefined name 'asdf'") doc.qutepart.cursorPosition = ((1, 0)) self.assertEqual(core.mainWindow().statusBar().currentMessage(), 'W391 blank line at end of file') doc.qutepart.cursorPosition = ((0, 1)) self.assertEqual(core.mainWindow().statusBar().currentMessage(), "F821 undefined name 'asdf'") doc.qutepart.text = 'def main()\n return 7' self.assertEqual(doc.qutepart.lintMarks, {}) self.assertEqual(core.mainWindow().statusBar().currentMessage(), "") doc.saveFile() self.waitUntilPassed( 2000, lambda: self.assertEqual( doc.qutepart.lintMarks, { 0: ('e', 'E901 SyntaxError: invalid syntax'), 1: ('w', 'E113 unexpected indentation') }))
def _install(self): """Install the plugin to the core """ if self._installed: return self._schemeMenu = core.actionManager().addMenu(self._MENU_PATH, self._FULL_NAME) self._evalAction = core.actionManager().addAction("%s/aEval" % self._MENU_PATH, "Eval. selection/Save and eval.") self._evalAction.setStatusTip("Evaluate selection. If nothing is selected, then save and evaluate whole file.") self._evalAction.setShortcut("Ctrl+E") self._evalAction.triggered.connect(self._onEvalTriggered) self._breakAction = core.actionManager().addAction("%s/aBreak" % self._MENU_PATH, "Stop the interpreter") self._breakAction.setStatusTip("Use it as a restart action.") self._breakAction.setShortcut("Pause") self._breakAction.triggered.connect(self._onBreakTriggered) #self._breakAction.setEnabled(False) if self._dock is None: from .repl import ReplDock self._dock = ReplDock(self._DOCK_TITLE, self._icon()) core.actionManager().addAction("mView/a%s" % self._LANGUAGE, self._dock.showAction()) core.mainWindow().addDockWidget(Qt.BottomDockWidgetArea, self._dock) self._installed = True
def _searchFile(self, forward=True, incremental=False): """Do search in file operation. Will select next found item """ qutepart = core.workspace().currentDocument().qutepart regExp = self._widget.getRegExp() if qutepart.absCursorPosition != self._searchInFileLastCursorPos: self._searchInFileStartPoint = None if self._searchInFileStartPoint is None or not incremental: # get cursor position cursor = qutepart.textCursor() if forward: if incremental : self._searchInFileStartPoint = cursor.selectionStart() else: self._searchInFileStartPoint = cursor.selectionEnd() else: self._searchInFileStartPoint = cursor.selectionStart() match, matches = self._searchInText(regExp, qutepart.text, self._searchInFileStartPoint, forward) if match: selectionStart, selectionEnd = match.start(), match.start() + len(match.group(0)) qutepart.absSelectedPosition = (selectionStart, selectionEnd) self._searchInFileLastCursorPos = selectionEnd self._widget.setState(self._widget.Good) # change background acording to result core.mainWindow().statusBar().showMessage('Match %d of %d' % \ (matches.index(match) + 1, len(matches)), 3000) else: self._widget.setState(self._widget.Bad) qutepart.resetSelection()
def setData(self, index, value, role=Qt.EditRole): document = self.document(index) newPath = value if newPath == document.filePath(): return False if newPath == '/dev/null': try: os.remove(document.filePath()) except (OSError, IOError) as ex: QMessageBox.critical(core.mainWindow(), 'Not this time', 'The OS thinks it needs the file') return False core.workspace().closeDocument(document) else: try: os.rename(document.filePath(), newPath) except (OSError, IOError) as ex: QMessageBox.critical(core.mainWindow(), 'Failed to rename file', str(ex)) return False else: document.setFilePath(newPath) document.saveFile() self.dataChanged.emit(index, index) return True
def _removeDock(self): """Remove dock from GUI """ core.actionManager().removeAction("mView/aPreview") core.actionManager().removeAction("mFile/aSavePreview") core.mainWindow().removeDockWidget(self._dock) self._dockInstalled = False
def _onResultsReady(self, document, results): # Check that the document with lint marks is still the current document. if core.workspace().currentDocument() is not document: return errors = 0 warnings = 0 visibleMessagesFilter = self._LEVEL_FILTER[core.config().get( 'Lint/Python/Show')] filteredResults = { lineNumber: value for lineNumber, value in results.items() if (value[0] in visibleMessagesFilter) } for level, message in filteredResults.values(): if level == Qutepart.LINT_ERROR: errors += 1 elif level == Qutepart.LINT_WARNING: warnings += 1 document.qutepart.lintMarks = filteredResults if document.qutepart.cursorPosition[0] in filteredResults: self._onCursorPositionChanged(document) # show msg on statusbar elif errors: core.mainWindow().statusBar().showMessage( 'Lint: {} error(s) found'.format(errors)) self._myMessageIsShown = True elif warnings: core.mainWindow().statusBar().showMessage( 'Lint: {} warning(s) found'.format(warnings)) self._myMessageIsShown = True
def _install(self): """Install the plugin to the core """ if self._installed: return self._schemeMenu = core.actionManager().addMenu(self._MENU_PATH, self._FULL_NAME) self._evalAction = core.actionManager().addAction("%s/aEval" % self._MENU_PATH, "Eval. selection/Save and eval.") self._evalAction.setStatusTip("Evaluate selection. If nothing is selected - save and evaluate whole file") self._evalAction.setShortcut("Ctrl+E") self._evalAction.triggered.connect(self._onEvalTriggered) self._breakAction = core.actionManager().addAction("%s/aBreak" % self._MENU_PATH, "Stop the interpreter") self._breakAction.setStatusTip("Use it as a restart action.") self._breakAction.setShortcut("Pause") self._breakAction.triggered.connect(self._onBreakTriggered) self._breakAction.setEnabled(False) self._activeInterpreterPath = self._settingsGroup()["InterpreterPath"] self._interpreter = self._createInterpreter() self._interpreter.processIsRunningChanged.connect(lambda isRunning: self._breakAction.setEnabled(isRunning)) if self._dock is None: from repl import ReplDock self._dock = ReplDock(self._interpreter.widget(), self._DOCK_TITLE, self._icon()) core.actionManager().addAction("mView/a%s" % self._LANGUAGE, self._dock.showAction()) core.mainWindow().addDockWidget(Qt.BottomDockWidgetArea, self._dock) self._installed = True
def _openSingleFile(self, filePath): """Open 1 file. Helper method, used by openFile() and openFiles() """ # Close 'untitled' if len(self.documents()) == 1 and \ self.documents()[0].fileName() is None and \ not self.documents()[0].filePath() and \ not self.documents()[0].qutepart.text and \ not self.documents()[0].qutepart.document().isModified(): self.closeDocument(self.documents()[0]) # check if file is already opened alreadyOpenedDocument = self.findDocumentForPath(filePath) if alreadyOpenedDocument is not None: self.setCurrentDocument( alreadyOpenedDocument ) return alreadyOpenedDocument # Check if exists, get stat try: statInfo = os.stat(filePath) except (OSError, IOError) as ex: QMessageBox.critical(self._mainWindow(), "Failed to stat the file", unicode(str(ex), 'utf8')) return None # Check if is a directory if stat.S_ISDIR(statInfo.st_mode): QMessageBox.critical(self._mainWindow(), "Can not open a directory", "{} is a directory".format(filePath)) return None # Check if too big if statInfo.st_size > _MAX_SUPPORTED_FILE_SIZE: msg = ("<html>" + \ "{} file size is {}.<br/>" + \ "I am a text editor, but not a data dump editor. I'm sory but I don't know how to open such a big files" + "</html>")\ .format(filePath, statInfo.st_size) QMessageBox.critical(self._mainWindow(), "Too big file", msg) return None # Check if have access to read if not os.access(filePath, os.R_OK): QMessageBox.critical(self._mainWindow(), "Don't have the access", "You don't have the read permission for {}".format(filePath)) return None # open the file document = Document(self, filePath) self._handleDocument( document ) if not os.access(filePath, os.W_OK): core.mainWindow().appendMessage( \ self.tr( "File '%s' is not writable" % filePath), 4000) # todo fix return document
def _searchWord(self, forward): """Do search in file operation. Will select next found item if updateWidget is True, search widget line edit will color will be set according to result """ document = core.workspace().currentDocument() cursor = document.qutepart.textCursor() if not cursor.hasSelection(): cursor.select(cursor.WordUnderCursor) word = cursor.selectedText() wordStartAbsPos = cursor.anchor() wordEndAbsPos = cursor.position() if not word: return regExp = re.compile('\\b%s\\b' % re.escape(word)) text = document.qutepart.text # avoid matching word under cursor if forward: startPoint = wordEndAbsPos else: startPoint = wordStartAbsPos self._updateFoundItemsHighlighting(regExp) match, matches = self._searchInText(regExp, document.qutepart.text, startPoint, forward) if match is not None: document.qutepart.absSelectedPosition = (match.start(), match.start() + len(match.group(0))) core.mainWindow().statusBar().showMessage('Match %d of %d' % \ (matches.index(match) + 1, len(matches)), 3000) else: core.workspace().currentDocument().qutepart.resetSelection()
def _openSingleFile(self, filePath): """Open 1 file. Helper method, used by openFile() and openFiles() """ # Close 'untitled' if len(self.documents()) == 1 and \ self.documents()[0].fileName() is None and \ not self.documents()[0].filePath() and \ not self.documents()[0].qutepart.text and \ not self.documents()[0].qutepart.document().isModified(): self.closeDocument(self.documents()[0]) # check if file is already opened alreadyOpenedDocument = self.findDocumentForPath(filePath) if alreadyOpenedDocument is not None: self.setCurrentDocument(alreadyOpenedDocument) return alreadyOpenedDocument # open file try: document = Document(self, filePath) except IOError as ex: QMessageBox.critical(None, self.tr("Failed to open file"), unicode(str(ex), 'utf8')) return None self._handleDocument(document) if not os.access(filePath, os.W_OK): core.mainWindow().appendMessage( \ self.tr( "File '%s' is not writable" % filePath), 4000) # todo fix return document
def _createSearchWidget(self): """ Create search widget. Called only when user requested it first time """ import searchwidget self._widget = searchwidget.SearchWidget( self ) self._widget.searchInDirectoryStartPressed.connect(self._onSearchInDirectoryStartPressed) self._widget.searchInDirectoryStopPressed.connect(self._onSearchInDirectoryStopPressed) self._widget.replaceCheckedStartPressed.connect(self._onReplaceCheckedStartPressed) self._widget.replaceCheckedStopPressed.connect(self._onReplaceCheckedStopPressed) self._widget.visibilityChanged.connect(self._updateSearchWidgetFoundItemsHighlighting) self._widget.searchRegExpChanged.connect(self._updateFileActionsState) self._widget.searchRegExpChanged.connect(self._onRegExpChanged) self._widget.searchRegExpChanged.connect(self._updateSearchWidgetFoundItemsHighlighting) self._widget.searchNext.connect(self._onSearchNext) self._widget.searchPrevious.connect(self._onSearchPrevious) self._widget.replaceFileOne.connect(self._onReplaceFileOne) self._widget.replaceFileAll.connect(self._onReplaceFileAll) core.workspace().currentDocumentChanged.connect(self._updateFileActionsState) # always disabled, if no widget core.workspace().currentDocumentChanged.connect(self._onCurrentDocumentChanged) core.workspace().textChanged.connect(self._updateSearchWidgetFoundItemsHighlighting) core.mainWindow().centralLayout().addWidget( self._widget ) self._widget.setVisible( False ) self._updateFileActionsState()
def _createDock(self): """Install dock """ # create dock if self._dock is None: if haveWebEngine: from enki.plugins.preview.preview import PreviewDock self._dock = PreviewDock() self._saveAction = QAction(QIcon(':enkiicons/save.png'), 'Save Preview as HTML', self._dock) self._saveAction.setShortcut(QKeySequence("Alt+Shift+P")) self._saveAction.triggered.connect(self._dock.onPreviewSave) else: self._dock = NoWebkitDock() if haveWebEngine: core.actionManager().addAction("mFile/aSavePreview", self._saveAction) self._dock.closed.connect(self._onDockClosed) self._dock.shown.connect(self._onDockShown) core.mainWindow().addDockWidget(Qt.RightDockWidgetArea, self._dock) core.actionManager().addAction("mView/aPreview", self._dock.showAction()) self._dockInstalled = True if core.config()['Preview']['Enabled']: self._dock.show()
def load(filePath, dataName, defaultValue): """Try to load data from JSON file. If something goes wrong - shows warnings to user. But, not if file not exists. dataName used in error messages. i.e. 'cursor positions', 'file browser settings' defaultValue is returned, if file not exists or if failed to load and parse it """ if not os.path.exists(filePath): return defaultValue try: with open(filePath, 'r') as openedFile: try: return json.load(openedFile) except Exception, ex: # broken file? error = unicode(str(ex), 'utf8') text = "Failed to parse %s file '%s': %s" % (dataName, filePath, error) core.mainWindow().appendMessage(text) print >> sys.stderr, text return defaultValue except (OSError, IOError), ex: error = unicode(str(ex), 'utf8') text = "Failed to load %s file '%s': %s" % (dataName, filePath, error) core.mainWindow().appendMessage(text) return defaultValue
def _saveSettings(self): """Flush main configuration file. """ try: core.config().flush() except UserWarning as ex: core.mainWindow().appendMessage(unicode(ex))
def _saveSettings(self): """Flush main configuration file. """ try: core.config().flush() except UserWarning as ex: core.mainWindow().appendMessage(str(ex))
def _onResultsReady(self, params): document, results = params errors = 0 warnings = 0 visibleMessagesFilter = self._LEVEL_FILTER[core.config().get('Lint/Python/Show')] filteredResults = {lineNumber: value \ for lineNumber, value in results.items() \ if (value[0] in visibleMessagesFilter)} for level, message in filteredResults.values(): if level == Qutepart.LINT_ERROR: errors += 1 elif level == Qutepart.LINT_WARNING: warnings += 1 document.qutepart.lintMarks = filteredResults if core.workspace().currentDocument() is document: if document.qutepart.cursorPosition[0] in filteredResults: self._onCursorPositionChanged(document) # show msg on statusbar elif errors: core.mainWindow().statusBar().showMessage('Lint: {} error(s) found'.format(errors)) elif warnings: core.mainWindow().statusBar().showMessage('Lint: {} warning(s) found'.format(warnings))
def _openSingleFile(self, filePath): """Open 1 file. Helper method, used by openFile() and openFiles() """ # Close 'untitled' if len(self.documents()) == 1 and \ self.documents()[0].fileName() is None and \ not self.documents()[0].filePath() and \ not self.documents()[0].qutepart.text and \ not self.documents()[0].qutepart.document().isModified(): self.closeDocument(self.documents()[0]) # check if file is already opened alreadyOpenedDocument = self.findDocumentForPath(filePath) if alreadyOpenedDocument is not None: self.setCurrentDocument( alreadyOpenedDocument ) return alreadyOpenedDocument # Check if exists, get stat try: statInfo = os.stat(filePath) except (OSError, IOError) as ex: QMessageBox.critical(self._mainWindow(), "Failed to stat the file", unicode(str(ex), 'utf8')) return None # Check if is a directory if stat.S_ISDIR(statInfo.st_mode): QMessageBox.critical(self._mainWindow(), "Can not open a directory", "{} is a directory".format(filePath)) return None # Check if too big if statInfo.st_size > _MAX_SUPPORTED_FILE_SIZE: msg = ("<html>" + \ "{} file size is {}.<br/>" + \ "I am a text editor, but not a data dump editor. I don't know how to open such a big files" + "</html>")\ .format(filePath, statInfo.st_size) QMessageBox.critical(self._mainWindow(), "Too big file", msg) return None # Check if have access to read if not os.access(filePath, os.R_OK): QMessageBox.critical(self._mainWindow(), "Don't have the access", "You don't have the read permission for {}".format(filePath)) return None # open the file document = Document(self, filePath) self._handleDocument( document ) if not os.access(filePath, os.W_OK): core.mainWindow().appendMessage( \ self.tr( "File '%s' is not writable" % filePath), 4000) # todo fix return document
def _searchWord(self, forward=True): """Do search in file operation. Will select next found item if updateWidget is True, search widget line edit will color will be set according to result """ document = core.workspace().currentDocument() word, wordStartAbsPos, wordEndAbsPos = document.wordUnderCursor() if word is None: return regExp = re.compile('\\b%s\\b' % re.escape(word)) text = document.text() # avoid matching word under cursor if forward: startPoint = wordEndAbsPos else: startPoint = wordStartAbsPos match, matches = self._searchInText(regExp, document.text(), startPoint, forward) if match is not None: document.goTo(absPos = match.start(), selectionLength = len(match.group(0))) core.mainWindow().statusBar().showMessage('Match %d of %d' % \ (matches.index(match) + 1, len(matches)), 3000) else: self._resetSelection(core.workspace().currentDocument())
def _install(self): """Install the plugin to the core """ if self._installed: return self._schemeMenu = core.actionManager().addMenu(self._MENU_PATH, self._FULL_NAME) self._evalAction = core.actionManager().addAction("%s/aEval" % self._MENU_PATH, "Eval. selection/Save and eval.") self._evalAction.setStatusTip("Evaluate selection. If nothing is selected - save and evaluate whole file") self._evalAction.setShortcut("Ctrl+E") self._evalAction.triggered.connect(self._onEvalTriggered) self._breakAction = core.actionManager().addAction("%s/aBreak" % self._MENU_PATH, "Stop the interpreter") self._breakAction.setStatusTip("Use it as a restart action.") self._breakAction.setShortcut("Pause") self._breakAction.triggered.connect(self._onBreakTriggered) self._breakAction.setEnabled(False) self._activeInterpreterPath = self._settingsGroup()["InterpreterPath"] self._interpreter = self._createInterpreter() self._interpreter.processIsRunningChanged.connect(lambda isRunning: self._breakAction.setEnabled(isRunning)) from repl import ReplDock self._dock = ReplDock(self._interpreter.widget(), self._LANGUAGE, self._DOCK_TITLE, self._icon()) core.mainWindow().addDockWidget(Qt.BottomDockWidgetArea, self._dock) self._dock.hide() self._installed = True
def main(): cmdLine = _parseCommandLine() profiler = _StartProfiler(cmdLine["profiling"]) try: _checkDependencies(profiler) except ImportError: sys.exit(-1) # Imports only here. Hack for ability to get help and version info even on system without PyQt. import PyQt5.QtGui import qutepart logging.basicConfig(level=logging.ERROR) logging.getLogger('qutepart').removeHandler(qutepart.consoleHandler) sys.excepthook = excepthook app = PyQt5.QtWidgets.QApplication(sys.argv) app.setApplicationName(enki.core.defines.PACKAGE_NAME) app.setOrganizationName(enki.core.defines.PACKAGE_ORGANISATION) app.setOrganizationDomain(enki.core.defines.PACKAGE_URL) app.lastWindowClosed.connect(app.quit) profiler.stepDone('Construct application') # init the core from enki.core.core import core core.init(profiler, cmdLine) _openFiles(core, cmdLine, profiler) profiler.stepDone('Open files') if core.workspace().currentDocument(): core.workspace().currentDocument().setFocus() core.mainWindow().loadState() profiler.stepDone('Load state') core.mainWindow().show() profiler.stepDone('Show main window') # execute application if profiler.enabled: core.workspace().forceCloseAllDocuments() result = 0 else: result = app.exec_() core.term() profiler.printInfo() profiler.stepDone('Terminate core') return result
def test_esc_on_editor_closes(self): QTest.keyClick(core.mainWindow(), Qt.Key_F, Qt.ControlModifier) widget = _findSearchController()._widget self.assertFalse(widget.isHidden()) QTest.keyClick(core.mainWindow(), Qt.Key_Return, Qt.ControlModifier) # focus to editor QTest.keyClick(core.workspace().currentDocument(), Qt.Key_Escape) self.assertTrue(widget.isHidden())
def _onLinkClicked(self, url): res = QDesktopServices.openUrl(url) if res: core.mainWindow().statusBar().showMessage( "{} opened in a browser".format(url.toString()), 2000) else: core.mainWindow().statusBar().showMessage( "Failed to open {}".format(url.toString()), 2000)
def _onCursorPositionChanged(self, document): lineNumber = document.qutepart.cursorPosition[0] if lineNumber in document.qutepart.lintMarks: msgType, msgText = document.qutepart.lintMarks[lineNumber] core.mainWindow().statusBar().showMessage(msgText) self._myMessageIsShown = True else: self._clearMessage()
def execWithArgs(): core.mainWindow().show() QTest.qWaitForWindowShown(core.mainWindow()) app = QApplication.instance() app.setActiveWindow(core.mainWindow()) assert app.focusWidget() is not None func(*args) # When done processing these events, exit the event loop. To do so, timer.start(0)
def __init__(self): """Create and install the plugin """ QObject.__init__(self) # create dock self.dock = DockFileBrowser(core.mainWindow()) self.dock.hide() # add dock to dock toolbar entry core.mainWindow().addDockWidget(Qt.LeftDockWidgetArea, self.dock)
def _onSearchThreadFinished(self): """Handler for search in directory finished signal """ self._widget.setSearchInProgress(False) matchesCount = self._dock.matchesCount() if matchesCount: core.mainWindow().statusBar().showMessage('%d matches ' % matchesCount, 3000) else: core.mainWindow().statusBar().showMessage('Nothing found', 3000)
def _onSearchThreadFinished(self): """Handler for search in directory finished signal """ self._widget.setSearchInProgress(False) matchesCount = self._dock.matchesCount() if matchesCount: core.mainWindow().statusBar().showMessage( '%d matches ' % matchesCount, 3000) else: core.mainWindow().statusBar().showMessage('Nothing found', 3000)
def execWithArgs(): core.mainWindow().show() QTest.qWaitForWindowShown(core.mainWindow()) while self.app.hasPendingEvents(): self.app.processEvents() try: func(*args) finally: self.app.quit()
def _createDockWidget(self): """Create dock widget, which displays search results. Called only when search in direcory process starts """ import searchresultsdock self._dock = searchresultsdock.SearchResultsDock(core.mainWindow()) core.mainWindow().addDockWidget(Qt.BottomDockWidgetArea, self._dock) self._dock.setVisible( False ) self._dock.setReplaceMode(self._mode == ModeReplaceDirectory or \ self._mode == ModeReplaceOpenedFiles)
def _install(self): if self._installed: return core.workspace().documentOpened.connect(self._onDocumentOpened) core.workspace().currentDocumentChanged.connect(self._onCurrentDocumentChanged) core.workspace().cursorPositionChanged.connect(self._onCursorPositionChanged) core.workspace().modificationChanged.connect(self._onModificationChanged) core.mainWindow().statusBar().messageChanged.connect(self._onStatusBarMessageChanged) self._installed = True
def _save(self): """Save the config """ if self._config: try: with open(_CONFIG_PATH, 'w') as f: json.dump(self._config, f, sort_keys=True, indent=4) except (OSError, IOError), ex: error = unicode(str(ex), 'utf8') text = "Failed to save shortcut settings file '%s': %s" % (_CONFIG_PATH, error) core.mainWindow().appendMessage(text)
def _createDockWidget(self): """Create dock widget, which displays search results. Called only when search in direcory process starts """ from . import searchresultsdock self._dock = searchresultsdock.SearchResultsDock(core.mainWindow()) core.mainWindow().addDockWidget(Qt.BottomDockWidgetArea, self._dock) self._dock.setVisible(False) self._dock.setReplaceMode(self._mode == MODE_REPLACE_DIRECTORY or self._mode == MODE_REPLACE_OPENED_FILES)
def _createDockWidget(self): """Create dock widget, which displays search results. Called only when search in direcory process starts """ import searchresultsdock self._dock = searchresultsdock.SearchResultsDock(core.mainWindow()) core.mainWindow().addDockWidget(Qt.BottomDockWidgetArea, self._dock) self._dock.setVisible( False ) self._dock.setReplaceMode(self._mode == MODE_REPLACE_DIRECTORY or \ self._mode == MODE_REPLACE_OPENED_FILES)
def _loadPopularDirs(self): """Load popular directories from the config """ self._popularDirs = {} if os.path.exists(self.FILE_PATH): try: with open(self.FILE_PATH, 'r') as f: self._popularDirs = json.load(f) except (OSError, IOError, ValueError), ex: error = unicode(str(ex), 'utf8') text = "Failed to load popular directories from '%s': %s" % (self.FILE_PATH, error) core.mainWindow().appendMessage(text)
def _onUndoClose(self): """Undo Close triggered. Open file """ existing = self._existingNotOpenedRecents() if not existing: core.mainWindow().statusBar().showMessage("No existing recent files") return doc = core.workspace().openFile(existing[0]) if doc is not None: # sucessfully opened self._recent.remove(existing[0])
def _saveFiles(self): """Saves all open files""" for document in core.workspace().documents(): if document.qutepart.document().isModified(): try: if not os.access(document.filePath(), os.W_OK): core.mainWindow().appendMessage( "Can not save file '%s', because it is not writable!" % document.filePath(), 4000) else: document.saveFile() except TypeError: pass # we don't have a path, so don't do anything
def dump(filePath, dataName, data, showWarnings=True): """Try to save data to JSON file. Show exceptions on main window and print it, if something goes wrong """ try: with open(filePath, 'w') as openedFile: json.dump(data, openedFile, sort_keys=True, indent=4) except (OSError, IOError) as ex: error = str(ex) text = "Failed to save %s to '%s': %s" % (dataName, filePath, error) if showWarnings and core.mainWindow() is not None: core.mainWindow().appendMessage(text) print(error, file=sys.stderr)
def _onResultActivated(self, index): """Item doubleclicked in the model, opening file """ result = index.internalPointer() if isinstance(result, searchresultsmodel.Result): fileResults = index.parent().internalPointer() core.workspace().goTo(result.fileName, line=result.line, column=result.column, selectionLength=len(result.match.group(0))) core.mainWindow().statusBar().showMessage( 'Match %d of %d' % (fileResults.results.index(result) + 1, len(fileResults.results)), 3000) self.setFocus()
def _getCurrentTemplate(self): path = self._getCurrentTemplatePath() if not path: return '' try: with open(path) as file: text = file.read() except Exception as ex: text = 'Failed to load template {}: {}'.format(path, ex) core.mainWindow().statusBar().showMessage(text) return '' else: return text