def notifyCallback(event): if event['path']: action = notifyActionToString(event['action']) if action: logging.info("Commit: " + action + " " + event['path']) QApplication.processEvents() return
def __scanDir(prefix, path, infoLabel=None): """Recursive scan for modules""" if infoLabel is not None: infoLabel.setText("Scanning " + path + "...") QApplication.processEvents() result = [] for item in os.listdir(path): if item in [".svn", ".cvs", ".git", ".hg"]: continue if os.path.isdir(path + item): result += __scanDir(prefix + item + ".", path + item + os.path.sep, infoLabel) continue if not isPythonFile(path + item): continue if item.startswith('__init__.'): if prefix != "": result.append(prefix[:-1]) continue nameParts = item.split('.') result.append(prefix + nameParts[0]) return result
def onRemoveCustomColors(self): """Removing the previously set custom colors""" if not self.__actionPrerequisites(): return # Memorize the current selection selection = self.serializeSelection() editor = self.selectedItems()[0].getEditor() with editor: for item in self.sortSelectedReverse(): if item.kind in [ CellElement.OPENED_GROUP_BEGIN, CellElement.COLLAPSED_GROUP, CellElement.EMPTY_GROUP ]: item.groupBeginCMLRef.removeCustomColors(editor) continue if item.isDocstring(): cmlComment = CMLVersion.find( item.ref.docstring.leadingCMLComments, CMLcc) else: cmlComment = CMLVersion.find(item.ref.leadingCMLComments, CMLcc) if cmlComment is not None: cmlComment.removeFromText(editor) QApplication.processEvents() self.parent().redrawNow() self.restoreSelectionByID(selection)
def onGroupEditTitle(self): """Edit (or view) the group title""" if not self.__actionPrerequisites(): return # Memorize the current selection selection = self.serializeSelection() dlg = ReplaceTextDialog('Group title', 'Group title:', self.parent()) # If it was one item selection and there was a previous text then # set it for editing if len(self.selectedItems()) == 1: title = self.selectedItems()[0].getTitle() if title: dlg.setText(title) if dlg.exec_(): newTitle = dlg.text() editor = self.selectedItems()[0].getEditor() with editor: for item in self.sortSelectedReverse(): item.groupBeginCMLRef.updateTitle(editor, newTitle) QApplication.processEvents() self.parent().redrawNow() self.restoreSelectionByID(selection)
def onSwitchIfBranch(self): """If primitive should switch the branches""" if not self.__actionPrerequisites(): return # Memorize the current selection selection = self.serializeSelection() # The selected items need to be sorted in the reverse line no oreder editor = self.selectedItems()[0].getEditor() with editor: for item in self.sortSelectedReverse(): if item.kind == CellElement.IF: cmlComment = CMLVersion.find(item.ref.leadingCMLComments, CMLsw) if cmlComment is None: # Did not exist, so needs to be generated line = CMLsw.generate(item.ref.body.beginPos) lineNo = item.getFirstLine() editor.insertLines(line, lineNo) else: # Existed, so it just needs to be deleted cmlComment.removeFromText(editor) QApplication.processEvents() self.parent().redrawNow() self.restoreSelectionByID(selection)
def leaveEvent(self, event): """Triggered when the cursor leaves the find results tree""" searchTooltip.setInside(False) QApplication.processEvents() hideSearchTooltip() QTreeWidget.leaveEvent(self, event)
def __notifyCallback(self, event): """Called by pysvn. event is a dictionary""" if 'path' not in event: return if not event['path']: return message = None path = event['path'] if os.path.isdir(path) and not path.endswith(os.path.sep): path += os.path.sep if event['action'] == pysvn.wc_notify_action.update_completed: message = path + " updated to revision " + str(event['revision'].number) elif event['action'] == pysvn.wc_notify_action.update_started: message = "updating " + path + ":" else: self.__updatedPaths.append(path) action = notifyActionToString(event['action']) if action is not None and action != "unknown": message = " " + action + " " + path if event['mime_type'] == "application/octet-stream": message += " (binary)" if message: self.__infoLabel.setText(message.strip()) logging.info(message) QApplication.processEvents()
def onGroup(self): """Groups items into a single one""" dlg = ReplaceTextDialog('Group title', 'Group title:', self.parent()) if dlg.exec_(): groupTitle = dlg.text() selected = self.__extendSelectionForGrouping() selected = self.sortSelected(selected) editor = selected[0].getEditor() firstLine, lastLine, pos = self.__getLineRange(selected) groupid = self.parent().generateNewGroupId() beginComment = CMLgb.generate(groupid, groupTitle, None, None, None, pos) endComment = CMLge.generate(groupid, pos) with editor: editor.insertLines(endComment, lastLine + 1) editor.insertLines(beginComment, firstLine) # Redraw the group collapsed fileName = editor._parent.getFileName() if not fileName: fileName = editor._parent.getShortName() addCollapsedGroup(fileName, groupid) QApplication.processEvents() self.parent().redrawNow()
def show(self): """Shows the tooltip at the proper position""" QToolTip.hideText() QApplication.processEvents() if self.__inside: self.move(self.__getTooltipPos()) self.raise_() QFrame.show(self)
def onEditDoc(self): """Editing the CML doc comment""" if not self.__actionPrerequisites(): return selectedItem = self.selectedItems()[0] # Exactly one is selected editor = selectedItem.getEditor() fileName = editor._parent.getFileName() if not fileName: fileName = editor._parent.getShortName() # It could be a CML doc or an item which has a CML doc if selectedItem.isComment(): cmlRef = selectedItem.cmlRef else: # If not found then it means the doc link needs to be created cmlRef = self.__findCMLinItem(selectedItem, CMLdoc) dlg = DocLinkAnchorDialog('Add' if cmlRef is None else 'Edit', cmlRef, fileName, self.parent()) if dlg.exec_(): link = dlg.linkEdit.text().strip() anchor = dlg.anchorEdit.text().strip() title = dlg.title() needToCreate = dlg.needToCreate() # First create a file if asked if needToCreate: docFileName = self.__createDocFile(link, fileName) if not docFileName: return selection = self.serializeSelection() with editor: # Now insert a new cml comment or update existing if cmlRef: # It is editing, the comment exists lineNo = cmlRef.ref.beginLine pos = cmlRef.ref.beginPos cmlRef.removeFromText(editor) bgColor = cmlRef.bgColor fgColor = cmlRef.fgColor border = cmlRef.border else: # It is a new doc link lineNo = selectedItem.getFirstLine() pos = selectedItem.ref.body.beginPos bgColor = None fgColor = None border = None line = CMLdoc.generate(link, anchor, title, bgColor, fgColor, border, pos) editor.insertLines(line, lineNo) QApplication.processEvents() self.parent().redrawNow() self.restoreSelectionByID(selection)
def __onRepeatedAction(self): """Repeated action""" for x in range(100): self.ide.mainWindow.em.newTabClicked(initialContent=None, shortName=str(x) + '.py', mime='text/x-python') QApplication.processEvents() self.ide.mainWindow.em.onCloseTab() QApplication.processEvents()
def closeEvent(self, event): """Window close event handler""" if self.__inProcess: self.__cancelRequest = True self.__infoLabel.setText("Cancelling...") QApplication.processEvents() event.ignore() else: event.accept()
def onAutoAddDoc(self): """Create a doc file, add a link and open for editing""" if not self.__actionPrerequisites(): return selectedItem = self.selectedItems()[0] # Exactly one is selected editor = selectedItem.getEditor() fileName = editor._parent.getFileName() if not fileName: logging.error('Save file before invoking auto doc') return needContent = False newAnchor = 'doc' + str(uuid.uuid4().fields[-1])[-6:] docFileName = self.__getAutoDocFileName(fileName) if not os.path.exists(docFileName): # Create file and populate with the default content try: os.makedirs(os.path.dirname(docFileName), exist_ok=True) with open(docFileName, 'w') as f: pass except Exception as exc: logging.error('Error creating the documentation file ' + docFileName + ': ' + str(exc)) return needContent = True project = GlobalData().project if project.isProjectFile(docFileName): link = project.getRelativePath(docFileName) else: link = os.path.relpath(docFileName, fileName) # Insert a doc link with editor: lineNo = selectedItem.getFirstLine() line = CMLdoc.generate(link, newAnchor, 'See documentation', None, None, None, selectedItem.ref.body.beginPos) editor.insertLines(line, lineNo) QApplication.processEvents() self.parent().redrawNow() # Open the file if GlobalData().mainWindow.openFile(docFileName, -1): if needContent: widget = GlobalData().mainWindow.em.getWidgetForFileName(docFileName) editor = widget.getEditor() editor.text = getDefaultFileDoc(fileName, newAnchor) editor.document().setModified(False)
def resize(self, controlItem): """Moves the popup to the proper position""" # calculate the positions above the group # Taken from here: # https://stackoverflow.com/questions/9871749/find-screen-position-of-a-qgraphicsitem scene = controlItem.ref.scene() view = scene.views()[0] sceneP = controlItem.mapToScene(controlItem.boundingRect().topLeft()) viewP = view.mapFromScene(sceneP) pos = view.viewport().mapToGlobal(viewP) self.move(pos.x(), pos.y() - self.height() - 2) QApplication.processEvents()
def __openedFiles(self, filters): """Currently opened editor buffers""" files = [] openedFiles = self.editorsManager.getTextEditors() for record in openedFiles: uuid = record[0] fname = record[1] if self.__filterMatch(filters, fname): files.append(ItemToSearchIn(fname, uuid)) QApplication.processEvents() if self.__cancelRequest: raise Exception("Cancel request") return files
def __notifyCallback(self, event): """Called by pysvn. event is a dictionary""" message = None if event['path']: action = notifyActionToString(event['action']) if action is not None and action != "unknown": message = action + " " + event['path'] if event['mime_type'] == "application/octet-stream": message += " (binary)" if message: self.__infoLabel.setText(message) QApplication.processEvents()
def onCustomColors(self): """Custom background and foreground colors""" if not self.__actionPrerequisites(): return # Memorize the current selection selection = self.serializeSelection() bgcolor, fgcolor, bordercolor = self.selectedItems()[0].getColors() hasDocstring = self.isDocstringInSelection() dlg = CustomColorsDialog(bgcolor, fgcolor, None if hasDocstring else bordercolor, self.parent()) if dlg.exec_(): bgcolor = dlg.backgroundColor() fgcolor = dlg.foregroundColor() bordercolor = dlg.borderColor() editor = self.selectedItems()[0].getEditor() with editor: for item in self.sortSelectedReverse(): if item.kind in [ CellElement.OPENED_GROUP_BEGIN, CellElement.COLLAPSED_GROUP, CellElement.EMPTY_GROUP ]: # The group always exists so just add/change the colors item.groupBeginCMLRef.updateCustomColors( editor, bgcolor, fgcolor, bordercolor) continue if item.isDocstring(): cmlComment = CMLVersion.find( item.ref.docstring.leadingCMLComments, CMLcc) else: cmlComment = CMLVersion.find( item.ref.leadingCMLComments, CMLcc) if cmlComment is not None: # Existed, so remove the old one first lineNo = cmlComment.ref.beginLine cmlComment.removeFromText(editor) else: lineNo = item.getFirstLine() pos = item.ref.body.beginPos if item.isDocstring(): pos = item.ref.docstring.beginPos line = CMLcc.generate(bgcolor, fgcolor, bordercolor, pos) editor.insertLines(line, lineNo) QApplication.processEvents() self.parent().redrawNow() self.restoreSelectionByID(selection)
def onRemoveDoc(self): """Removing the CML doc comment""" if not self.__actionPrerequisites(): return editor = self.selectedItems()[0].getEditor() with editor: for item in self.sortSelectedReverse(): cmlComment = CMLVersion.find(item.ref.leadingCMLComments, CMLdoc) if cmlComment is not None: cmlComment.removeFromText(editor) QApplication.processEvents() self.parent().redrawNow()
def killAll(self): """Kills all the processes if needed""" index = len(self.__processes) - 1 while index >= 0: item = self.__processes[index] if item.procWrapper.redirected: item.procWrapper.stop() index -= 1 # Wait till all the processes stopped count = self.__getDetachedCount() while count > 0: time.sleep(0.01) QApplication.processEvents() count = self.__getDetachedCount()
def onRemoveReplacementText(self): """Removing replacement text""" if self.__actionPrerequisites(): # Memorize the current selection selection = self.serializeSelection() editor = self.selectedItems()[0].getEditor() with editor: for item in self.sortSelectedReverse(): cmlComment = CMLVersion.find(item.ref.leadingCMLComments, CMLrt) if cmlComment is not None: cmlComment.removeFromText(editor) QApplication.processEvents() self.parent().redrawNow() self.restoreSelectionByID(selection)
def show(self, controlItem): """Shows the title above the group control""" # Use the palette from the group bgColor, fgColor, _ = controlItem.ref.getColors() palette = self.__titleLabel.palette() palette.setColor(QPalette.Background, bgColor) palette.setColor(QPalette.Foreground, fgColor) self.__titleLabel.setPalette(palette) # That's a trick: resizing works correctly only if the item is shown # So move it outside of the screen, show it so it is invisible and then # resize and move to the proper position screenHeight = GlobalData().screenHeight self.move(0, screenHeight + 128) QFrame.show(self) QApplication.processEvents() self.resize(controlItem)
def onGroupUngroup(self): """Ungroups the items""" if not self.__actionPrerequisites(): return # Memorize the current selection selection = self.serializeSelection() # The selected items need to be sorted in the reverse line no oreder editor = self.selectedItems()[0].getEditor() with editor: for item in self.sortSelectedReverse(): item.groupEndCMLRef.removeFromText(editor) item.groupBeginCMLRef.removeFromText(editor) QApplication.processEvents() self.parent().redrawNow() self.restoreSelectionByTooltip(selection)
def onGroupExpand(self): """Expands the selected group""" if not self.__actionPrerequisites(): return # The selected items need to be sorted in the reverse line no oreder editor = self.selectedItems()[0].getEditor() with editor: for item in self.sortSelectedReverse(): if item.kind == CellElement.COLLAPSED_GROUP: fileName = editor._parent.getFileName() if not fileName: fileName = editor._parent.getShortName() removeCollapsedGroup(fileName, item.getGroupId()) QApplication.processEvents() self.parent().redrawNow()
def __process(self): """Update process""" QApplication.processEvents() self.__client.callback_cancel = self.__cancelCallback self.__client.callback_notify = self.__notifyCallback try: self.__inProcess = True self.annotation = self.__client.annotate(self.__path, self.__revStart, self.__revEnd, self.__revPeg) self.__collectRevisionInfo() self.__inProcess = False except pysvn.ClientError as exc: errorCode = exc.args[1][0][1] if errorCode == pysvn.svn_err.cancelled: logging.info("Annotating of '" + self.__path + "' cancelled") else: message = exc.args[0] logging.error(message) self.__inProcess = False self.close() return except Exception as exc: logging.error(str(exc)) self.__inProcess = False self.close() return except: logging.error("Unknown error") self.__inProcess = False self.close() return if self.__cancelRequest: self.close() else: self.accept()
def __projectFiles(self, filters): """Project files list respecting the mask""" mainWindow = GlobalData().mainWindow files = [] for fname in GlobalData().project.filesList: if fname.endswith(sep): continue if self.__filterMatch(filters, fname): widget = mainWindow.getWidgetForFileName(fname) if widget is None: # Do not check for broken symlinks if isFileSearchable(fname, False): files.append(ItemToSearchIn(fname, "")) else: if widget.getType() in \ [MainWindowTabWidgetBase.PlainTextEditor]: files.append(ItemToSearchIn(fname, widget.getUUID())) QApplication.processEvents() if self.__cancelRequest: raise Exception("Cancel request") return files
def onRemoveCustomColors(self): """Removing the previously set custom colors""" if not self.__actionPrerequisites(): return # Memorize the current selection selection = self.serializeSelection() editor = self.selectedItems()[0].getEditor() with editor: # Remove colors is done via delete/insert for the Doc and group # items. So it is safer to do first because the cc comment may be # in a set of selected which is inserted before the doc cml and # thus breaks the line numbering for item in self.selectedItems(): # The doc always exists if item.isCMLDoc(): item.cmlRef.removeCustomColors(editor) continue # The group always exists if item.isGroupItem(): item.groupBeginCMLRef.removeCustomColors(editor) # Now handle the rest of items for item in self.sortSelectedReverse(): if item.isCMLDoc() or item.isGroupItem(): continue if item.isDocstring(): cmlComment = CMLVersion.find( item.ref.docstring.leadingCMLComments, CMLcc) else: cmlComment = CMLVersion.find( item.ref.leadingCMLComments, CMLcc) if cmlComment is not None: cmlComment.removeFromText(editor) QApplication.processEvents() self.parent().redrawNow() self.restoreSelectionByID(selection)
def onReplaceText(self): """Replace the code with a title""" if not self.__actionPrerequisites(): return # Memorize the current selection selection = self.serializeSelection() dlg = ReplaceTextDialog('Replace text', 'Item caption:', self.parent()) # If it was one item selection and there was a previous text then # set it for editing if len(self.selectedItems()) == 1: cmlComment = CMLVersion.find( self.selectedItems()[0].ref.leadingCMLComments, CMLrt) if cmlComment is not None: dlg.setText(cmlComment.getText()) if dlg.exec_(): replacementText = dlg.text() editor = self.selectedItems()[0].getEditor() with editor: for item in self.sortSelectedReverse(): cmlComment = CMLVersion.find( item.ref.leadingCMLComments, CMLrt) if cmlComment is not None: # Existed, so remove the old one first lineNo = cmlComment.ref.beginLine cmlComment.removeFromText(editor) else: lineNo = item.getFirstLine() line = CMLrt.generate(replacementText, item.ref.body.beginPos) editor.insertLines(line, lineNo) QApplication.processEvents() self.parent().redrawNow() self.restoreSelectionByID(selection)
def __onDebugger(self): """Brings up a debugger""" heap = self.hpy.heap() unreachable = self.hpy.heapu() logging.error( "Use 'heap' and 'unreachable' objects. Type 'c' when finished.") QApplication.processEvents() oldstdin = sys.stdin oldstdout = sys.stdout oldstderr = sys.stderr sys.stdin = sys.__stdin__ sys.stdout = sys.__stdout__ sys.stderr = sys.__stderr__ pyqtRemoveInputHook() pdb.set_trace() pyqtRestoreInputHook() sys.stdin = oldstdin sys.stdout = oldstdout sys.stderr = oldstderr
def __dirFiles(self, path, filters, files): """Files recursively for the dir""" for item in listdir(path): QApplication.processEvents() if self.__cancelRequest: raise Exception("Cancel request") if isdir(path + item): if item in ['.svn', '.cvs', '.git', '.hg']: # It does not make sense to search in revision control dirs continue anotherDir, isLoop = resolveLink(path + item) if not isLoop: self.__dirFiles(anotherDir + sep, filters, files) continue if not isfile(path + item): continue realItem, isLoop = resolveLink(path + item) if isLoop: continue if self.__filterMatch(filters, realItem): found = False for itm in files: if itm.fileName == realItem: found = True break if not found: mainWindow = GlobalData().mainWindow widget = mainWindow.getWidgetForFileName(realItem) if widget is None: if isFileSearchable(realItem): files.append(ItemToSearchIn(realItem, "")) else: if widget.getType() in \ [MainWindowTabWidgetBase.PlainTextEditor]: files.append(ItemToSearchIn(realItem, widget.getUUID()))
def __collectRevisionInfo(self): """Collects information about revision messages""" self.__infoLabel.setText("Collecting revision messages...") QApplication.processEvents() revisions = set() for item in self.annotation: if item['revision'].kind == pysvn.opt_revision_kind.number: revisions.add(item['revision'].number) self.revisionsInfo = {} minRevision = min(revisions) maxRevision = max(revisions) revStart = pysvn.Revision(pysvn.opt_revision_kind.number, minRevision) revEnd = pysvn.Revision(pysvn.opt_revision_kind.number, maxRevision) revs = self.__client.log(self.__path, revision_start=revStart, revision_end=revEnd) for rev in revs: if rev['revision'].kind == pysvn.opt_revision_kind.number: number = rev['revision'].number if number in revisions: self.revisionsInfo[number] = {'message': rev['message']}