def actionTriggered(self, name): # convert arpeggio_normal to arpeggioNormal, etc. name = _arpeggioTypes[name] cursor = self.mainwindow().textCursor() # which arpeggio type is last used? lastused = '\\arpeggioNormal' types = set(_arpeggioTypes.values()) block = cursor.block() while block.isValid(): s = types.intersection(tokeniter.tokens(block)) if s: lastused = s.pop() break block = block.previous() # where to insert c = lydocument.cursor(cursor) c.select_end_of_block() with cursortools.compress_undo(cursor): for item in ly.rhythm.music_items(c, partial=ly.document.OUTSIDE): c = QTextCursor(cursor.document()) c.setPosition(item.end) c.insertText('\\arpeggio') if name != lastused: cursortools.strip_indent(c) indent = c.block().text()[:c.position() - c.block().position()] c.insertText(name + '\n' + indent) # just pick the first place return
def actionTriggered(self, name): # convert arpeggio_normal to arpeggioNormal, etc. name = _arpeggioTypes[name] cursor = self.mainwindow().textCursor() # which arpeggio type is last used? lastused = '\\arpeggioNormal' types = set(_arpeggioTypes.values()) block = cursor.block() while block.isValid(): s = types.intersection(tokeniter.tokens(block)) if s: lastused = s.pop() break block = block.previous() # where to insert c = lydocument.cursor(cursor) c.select_end_of_block() with cursortools.compress_undo(cursor): for item in ly.rhythm.music_items(c, partial=ly.document.OUTSIDE): c = QTextCursor(cursor.document()) c.setPosition(item.end) c.insertText('\\arpeggio') if name != lastused: cursortools.strip_indent(c) indent = c.block().text()[:c.position()-c.block().position()] c.insertText(name + '\n' + indent) # just pick the first place return
def cursors(self): """Cursors for rectangular selection. 1 cursor for every line """ cursors = [] if self._start is not None: startLine, startVisibleCol = self._start currentLine, currentCol = self._qpart.cursorPosition if abs(startLine - currentLine) > self._MAX_SIZE or \ abs(startVisibleCol - currentCol) > self._MAX_SIZE: # Too big rectangular selection freezes the GUI self._qpart.userWarning.emit('Rectangular selection area is too big') self._start = None return [] currentBlockText = self._qpart.textCursor().block().text() currentVisibleCol = self._realToVisibleColumn(currentBlockText, currentCol) for lineNumber in range(min(startLine, currentLine), max(startLine, currentLine) + 1): block = self._qpart.document().findBlockByNumber(lineNumber) cursor = QTextCursor(block) realStartCol = self._visibleToRealColumn(block.text(), startVisibleCol) realCurrentCol = self._visibleToRealColumn(block.text(), currentVisibleCol) if realStartCol is None: realStartCol = block.length() # out of range value if realCurrentCol is None: realCurrentCol = block.length() # out of range value cursor.setPosition(cursor.block().position() + min(realStartCol, block.length() - 1)) cursor.setPosition(cursor.block().position() + min(realCurrentCol, block.length() - 1), QTextCursor.KeepAnchor) cursors.append(cursor) return cursors
def on_log_received(self, data): time_info = datetime.fromtimestamp((data['time'] / 1000)).isoformat() log_message = '%s: %s : %s' % ( time_info, data['level'], data['message']) message_document = self.document() cursor_to_add = QTextCursor(message_document) cursor_to_add.movePosition(cursor_to_add.End) cursor_to_add.insertText(log_message + '\n') if data['level'] in COLORS: fmt = QTextCharFormat() fmt.setForeground(COLORS[data['level']]) cursor_to_add.movePosition(cursor_to_add.PreviousBlock) log_lvl_data = LogLevelData(log_levels[data['level'].upper()]) cursor_to_add.block().setUserData(log_lvl_data) cursor_to_add_fmt = message_document.find(data['level'], cursor_to_add.position()) cursor_to_add_fmt.mergeCharFormat(fmt) if log_levels[data['level']] > self.log_lvl: cursor_to_add.block().setVisible(False) self.ensureCursorVisible()
def on_log_received(self, data): time_info = datetime.fromtimestamp((data['time'] / 1000)).isoformat() log_message = '%s: %s : %s' % (time_info, data['level'], data['message']) message_document = self.document() cursor_to_add = QTextCursor(message_document) cursor_to_add.movePosition(cursor_to_add.End) cursor_to_add.insertText(log_message + '\n') if data['level'] in COLORS: fmt = QTextCharFormat() fmt.setForeground(COLORS[data['level']]) cursor_to_add.movePosition(cursor_to_add.PreviousBlock) log_lvl_data = LogLevelData(log_levels[data['level'].upper()]) cursor_to_add.block().setUserData(log_lvl_data) cursor_to_add_fmt = message_document.find(data['level'], cursor_to_add.position()) cursor_to_add_fmt.mergeCharFormat(fmt) if log_levels[data['level']] > self.log_lvl: cursor_to_add.block().setVisible(False) self.ensureCursorVisible()
def highlightHorizontalLine(self, text, cursor, bf, strt): found = False for mo in re.finditer(self.MARKDOWN_KEYS_REGEX['HR'],text): prevBlock = self.currentBlock().previous() prevCursor = QTextCursor(prevBlock) prev = prevBlock.text() prevAscii = str(prev.replace(u'\u2029','\n')) if prevAscii.strip(): #print "Its a header" prevCursor.select(QTextCursor.LineUnderCursor) #prevCursor.setCharFormat(self.MARKDOWN_KWS_FORMAT['Header']) formatRange = QTextLayout.FormatRange() formatRange.format = self.MARKDOWN_KWS_FORMAT['Header'] formatRange.length = prevCursor.block().length() formatRange.start = 0 prevCursor.block().layout().setAdditionalFormats([formatRange]) self.setFormat(mo.start()+strt, mo.end() - mo.start(), self.MARKDOWN_KWS_FORMAT['HR']) for mo in re.finditer(self.MARKDOWN_KEYS_REGEX['eHR'],text): prevBlock = self.currentBlock().previous() prevCursor = QTextCursor(prevBlock) prev = prevBlock.text() prevAscii = str(prev.replace(u'\u2029','\n')) if prevAscii.strip(): #print "Its a header" prevCursor.select(QTextCursor.LineUnderCursor) #prevCursor.setCharFormat(self.MARKDOWN_KWS_FORMAT['Header']) formatRange = QTextLayout.FormatRange() formatRange.format = self.MARKDOWN_KWS_FORMAT['Header'] formatRange.length = prevCursor.block().length() formatRange.start = 0 prevCursor.block().layout().setAdditionalFormats([formatRange]) self.setFormat(mo.start()+strt, mo.end() - mo.start(), self.MARKDOWN_KWS_FORMAT['HR']) return found
def on_log_filter(self): log_lvl_name = str(self.sender().iconText()).upper() self.log_lvl = log_levels[log_lvl_name] cursor = QTextCursor(self.document()) current_block = cursor.block() while current_block.isValid() and current_block.userData(): block_log_lvl = current_block.userData().log_lvl if block_log_lvl <= self.log_lvl: current_block.setVisible(True) else: current_block.setVisible(False) current_block = current_block.next() self.viewport().update()
def indent_line(self, line_no, indent_length): block = self._get_block(line_no) cursor = QTextCursor(block) cursor.joinPreviousEditBlock() cursor.movePosition(QTextCursor.StartOfBlock, QTextCursor.MoveAnchor) if indent_length < 0: for i in range(-indent_length): cursor.deleteChar() else: cursor.insertText(" " * indent_length) if indent_length: cursor.movePosition(QTextCursor.StartOfBlock, QTextCursor.MoveAnchor) line = unicode(cursor.block().text()) if len(line) and line[0] == " ": cursor.movePosition(QTextCursor.NextWord, QTextCursor.MoveAnchor) self.editview.setTextCursor(cursor) cursor.endEditBlock()
def indent_line(self, line_no, indent_length): block = self._get_block(line_no) cursor = QTextCursor(block) cursor.joinPreviousEditBlock() cursor.movePosition(QTextCursor.StartOfBlock, QTextCursor.MoveAnchor) if indent_length < 0: for i in range(-indent_length): cursor.deleteChar() else: cursor.insertText(" " * indent_length) if indent_length: cursor.movePosition( QTextCursor.StartOfBlock, QTextCursor.MoveAnchor) line = unicode(cursor.block().text()) if len(line) and line[0] == " ": cursor.movePosition( QTextCursor.NextWord, QTextCursor.MoveAnchor) self.editview.setTextCursor(cursor) cursor.endEditBlock()
class Log(QTextBrowser): """Widget displaying output from a Job.""" def __init__(self, parent=None): super(Log, self).__init__(parent) self.setOpenLinks(False) self.cursor = QTextCursor(self.document()) self._types = job.ALL self._lasttype = None self._formats = self.logformats() def setMessageTypes(self, types): """Set the types of Job output to display. types is a constant bitmask from job, like job.STDOUT etc. By default job.ALL is used. """ self._types = types def messageTypes(self): """Return the set message types (job.ALL by default).""" return self._types def connectJob(self, job): """Gives us the output from the Job (past and upcoming).""" for msg, type in job.history(): self.write(msg, type) job.output.connect(self.write) def textFormat(self, type): """Returns a QTextFormat() for the given type.""" return self._formats[type] def write(self, message, type): """Writes the given message with the given type to the log. The keepScrolledDown context manager is used to scroll the log further down if it was scrolled down at that moment. If two messages of a different type are written after each other a newline is inserted if otherwise the message would continue on the same line. """ if type & self._types: with self.keepScrolledDown(): changed = type != self._lasttype self._lasttype = type if changed and self.cursor.block().text() and not message.startswith('\n'): self.cursor.insertText('\n') self.writeMessage(message, type) def writeMessage(self, message, type): """Inserts the given message in the text with the textformat belonging to type.""" self.cursor.insertText(message, self.textFormat(type)) @contextlib.contextmanager def keepScrolledDown(self): """Performs a function, ensuring the log stays scrolled down if it was scrolled down on start.""" vbar = self.verticalScrollBar() scrolleddown = vbar.value() == vbar.maximum() try: yield finally: if scrolleddown: vbar.setValue(vbar.maximum()) def logformats(self): """Returns a dictionary with QTextCharFormats for the different types of messages. Besides the STDOUT, STDERR, NEUTRAL, FAILURE and SUCCESS formats there is also a "link" format, that looks basically the same as the output formats, but blueish and underlined, to make parts of the output (e.g. filenames) look clickable. """ textColor = QApplication.palette().color(QPalette.WindowText) successColor = qutil.addcolor(textColor, 0, 128, 0) # more green failureColor = qutil.addcolor(textColor, 128, 0, 0) # more red linkColor = qutil.addcolor(textColor, 0, 0, 128) # more blue stdoutColor = qutil.addcolor(textColor, 64, 64, 0) # more purple s = QSettings() s.beginGroup("log") outputFont = QFont(s.value("fontfamily", "monospace", type(""))) outputFont.setPointSizeF(s.value("fontsize", 9.0, float)) output = QTextCharFormat() output.setFont(outputFont) # enable zooming the log font size output.setProperty(QTextFormat.FontSizeAdjustment, 0) stdout = QTextCharFormat(output) stdout.setForeground(stdoutColor) stderr = QTextCharFormat(output) link = QTextCharFormat(output) link.setForeground(linkColor) link.setFontUnderline(True) status = QTextCharFormat() status.setFontWeight(QFont.Bold) neutral = QTextCharFormat(status) success = QTextCharFormat(status) success.setForeground(successColor) failure = QTextCharFormat(status) failure.setForeground(failureColor) return { job.STDOUT: stdout, job.STDERR: stderr, job.NEUTRAL: neutral, job.SUCCESS: success, job.FAILURE: failure, 'link': link, }