def pixmap(cursor, num_lines=6, scale=0.8): """Return a QPixmap displaying the selected lines of the document. If the cursor has no selection, num_lines are drawn. By default the text is drawn 0.8 * the normal font size. You can change that by supplying the scale parameter. """ block = cursor.document().findBlock(cursor.selectionStart()) c2 = QTextCursor(block) if cursor.hasSelection(): c2.setPosition(cursor.selectionEnd(), QTextCursor.KeepAnchor) c2.movePosition(QTextCursor.EndOfBlock, QTextCursor.KeepAnchor) else: c2.movePosition(QTextCursor.NextBlock, QTextCursor.KeepAnchor, num_lines) data = textformats.formatData('editor') doc = QTextDocument() font = QFont(data.font) font.setPointSizeF(font.pointSizeF() * scale) doc.setDefaultFont(font) doc.setPlainText(c2.selection().toPlainText()) if metainfo.info(cursor.document()).highlighting: highlighter.highlight(doc, state=tokeniter.state(block)) size = doc.size().toSize() + QSize(8, -4) pix = QPixmap(size) pix.fill(data.baseColors['background']) doc.drawContents(QPainter(pix)) return pix
def edit(self, cursor): """Edit the block at the specified QTextCursor.""" if self._document: self._document.closed.disconnect(self.reject) self._document = cursor.document() self._document.closed.connect(self.reject) # don't change the cursor c = self._range = QTextCursor(cursor) cursorpos = c.position() - c.block().position() cursortools.strip_indent(c) indentpos = c.position() - c.block().position() c.movePosition(QTextCursor.EndOfBlock, QTextCursor.KeepAnchor) self.view.setPlainText(c.selection().toPlainText()) self.highlighter.setInitialState(tokeniter.state(cursortools.block(cursor))) self.highlighter.setHighlighting(metainfo.info(cursor.document()).highlighting) self.highlighter.rehighlight() # let autocomplete query the real document as if we're at the start # of the current block self.completer.document_cursor = QTextCursor(cursor.block()) self.completer.autoComplete = QSettings().value("autocomplete", True, bool) cursor = self.view.textCursor() cursor.setPosition(max(0, cursorpos-indentpos)) self.view.setTextCursor(cursor) self.updateMessage()
def updateDocActions(self, doc): minfo = metainfo.info(doc) if minfo.highlighting: highlighter.highlighter(doc) ac = self.actionCollection ac.view_highlighting.setChecked(minfo.highlighting) ac.tools_indent_auto.setChecked(minfo.auto_indent)
def edit(self, cursor): """Edit the block at the specified QTextCursor.""" if self._document: self._document.closed.disconnect(self.reject) self._document = cursor.document() self._document.closed.connect(self.reject) # don't change the cursor c = self._range = QTextCursor(cursor) cursorpos = c.position() - c.block().position() cursortools.strip_indent(c) indentpos = c.position() - c.block().position() c.movePosition(QTextCursor.EndOfBlock, QTextCursor.KeepAnchor) self.view.setPlainText(c.selection().toPlainText()) self.highlighter.setInitialState( tokeniter.state(cursortools.block(cursor))) self.highlighter.setHighlighting( metainfo.info(cursor.document()).highlighting) self.highlighter.rehighlight() # let autocomplete query the real document as if we're at the start # of the current block self.completer.document_cursor = QTextCursor(cursor.block()) self.completer.autoComplete = QSettings().value("autocomplete", True) not in ('false', False) cursor = self.view.textCursor() cursor.setPosition(max(0, cursorpos - indentpos)) self.view.setTextCursor(cursor) self.updateMessage()
def show(cursor, pos=None, num_lines=6): """Displays a tooltip showing part of the cursor's Document. If the cursor has a selection, those blocks are displayed. Otherwise, num_lines lines are displayed. If pos is not given, the global mouse position is used. """ block = cursor.document().findBlock(cursor.selectionStart()) c2 = QTextCursor(block) if cursor.hasSelection(): c2.setPosition(cursor.selectionEnd(), QTextCursor.KeepAnchor) c2.movePosition(QTextCursor.EndOfBlock, QTextCursor.KeepAnchor) else: c2.movePosition(QTextCursor.NextBlock, QTextCursor.KeepAnchor, num_lines) data = textformats.formatData('editor') doc = QTextDocument() font = QFont(data.font) font.setPointSizeF(font.pointSizeF() * .8) doc.setDefaultFont(font) doc.setPlainText(c2.selection().toPlainText()) if metainfo.info(cursor.document()).highlighting: highlighter.highlight(doc, state=tokeniter.state(block)) size = doc.size().toSize() + QSize(8, -4) pix = QPixmap(size) pix.fill(data.baseColors['background']) doc.drawContents(QPainter(pix)) label = QLabel() label.setPixmap(pix) label.setStyleSheet("QLabel { border: 1px solid #777; }") label.resize(size) widgets.customtooltip.show(label, pos)
def cut_assign(cursor): """Cuts selected text and assigns it to a LilyPond variable.""" # ask the variable name name = inputdialog.getText(None, _("Cut and Assign"), _( "Please enter the name for the variable to assign the selected " "text to:"), regexp="[A-Za-z]+") if not name: return cursortools.strip_selection(cursor) # determine state at cursor block = cursortools.block(cursor) state = tokeniter.state(block) for t in tokeniter.partition(cursor).left: state.follow(t) mode = "" for p in state.parsers(): if isinstance(p, ly.lex.lilypond.ParseInputMode): if isinstance(p, ly.lex.lilypond.ParseLyricMode): mode = " \\lyricmode" elif isinstance(p, ly.lex.lilypond.ParseChordMode): mode = " \\chordmode" elif isinstance(p, ly.lex.lilypond.ParseFigureMode): mode = " \\figuremode" elif isinstance(p, ly.lex.lilypond.ParseDrumMode): mode = " \\drummode" break # find insertion place: found = False while block.previous().isValid(): block = block.previous() state = tokeniter.state(block) if isinstance(state.parser(), ly.lex.lilypond.ParseGlobal): found = True break tokens = tokeniter.tokens(block) for t in tokens: if isinstance(t, ly.lex.lilypond.Name): found = True break elif not isinstance(t, (ly.lex.Space, ly.lex.Comment)): break if found: break insert = QTextCursor(block) text = cursor.selection().toPlainText() space = '\n' if '\n' in text else ' ' text = ''.join((name, ' =', mode, ' {', space, text, space, '}\n\n')) with cursortools.compress_undo(cursor): cursor.insertText('\\' + name) pos = insert.selectionStart() insert.insertText(text) if metainfo.info(cursor.document()).auto_indent: insert.setPosition(pos, QTextCursor.KeepAnchor) with cursortools.compress_undo(insert, True): indent.re_indent(insert)
def jobFinished(self, document, j, success): if document == self.viewSpace().document(): self._bar.setShowFinished( success and not job.attributes.get(j).hidden ) self._bar.stop() if success: metainfo.info(document).buildtime = j.elapsed_time()
def __init__(self, document): QSyntaxHighlighter.__init__(self, document) self._fridge = ly.lex.Fridge() app.settingsChanged.connect(self.rehighlight) self._highlighting = metainfo.info(document).highlighting document.loaded.connect(self._resetHighlighting) self._mode = documentinfo.mode(document, False) variables.manager(document).changed.connect(self._variablesChange)
def showProgress(self, document): job = jobmanager.job(document) if job and job.isRunning(): buildtime = metainfo.info(document).buildtime if not buildtime: buildtime = 3.0 + document.blockCount() / 20 # very arbitrary estimate... self._bar.start(buildtime, job.elapsed()) else: self._bar.stop(False)
def htmlCopy(document, type='editor'): """Return a new QTextDocument with highlighting set as HTML textcharformats.""" data = textformats.formatData(type) doc = QTextDocument() doc.setDefaultFont(data.font) doc.setPlainText(document.toPlainText()) if metainfo.info(document).highlighting: highlight(doc, HighlightFormats(data), ly.lex.state(documentinfo.mode(document))) return doc
def save(self): """Saves the marks to the metainfo.""" d = {} for type in types: d[type] = lines = [] for mark in self._marks[type]: linenum = mark.blockNumber() if linenum not in lines: lines.append(linenum) metainfo.info(self.document()).bookmarks = json.dumps(d)
def load(self): """Loads the marks from the metainfo.""" self._marks = dict((type, []) for type in types) marks = metainfo.info(self.document()).bookmarks try: d = json.loads(marks) or {} except ValueError: return # No JSON object could be decoded for type in types: self._marks[type] = [QTextCursor(self.document().findBlockByNumber(num)) for num in d.get(type, [])] self.marksChanged()
def keyPressEvent(self, ev): super(View, self).keyPressEvent(ev) if metainfo.info(self.document()).auto_indent: # run the indenter on Return or when the user entered a dedent token. import indent cursor = self.textCursor() if ev.text() == '\r' or (ev.text() in ('}', '#', '>') and indent.indentable(cursor)): indent.auto_indent_block(cursor.block()) # fix subsequent vertical moves cursor.setPosition(cursor.position()) self.setTextCursor(cursor)
def initializeDocument(self): """This method is always called by the __init__ method. The default implementation does nothing for generic QTextDocuments, but for document.Document instances it connects to some additional signals to keep the mode up-to-date (reading it from the variables if needed) and initializes whether to enable visual highlighting from the document's metainfo. """ document = self.document() if hasattr(document, "url"): self._highlighting = metainfo.info(document).highlighting document.loaded.connect(self._resetHighlighting) self._mode = documentinfo.mode(document, False) variables.manager(document).changed.connect(self._variablesChange)
def initializeDocument(self): """This method is always called by the __init__ method. The default implementation does nothing for generic QTextDocuments, but for document.Document instances it connects to some additional signals to keep the mode up-to-date (reading it from the variables if needed) and initializes whether to enable visual highlighting from the document's metainfo. """ document = self.document() if hasattr(document, 'url'): self._highlighting = metainfo.info(document).highlighting document.loaded.connect(self._resetHighlighting) self._mode = documentinfo.mode(document, False) variables.manager(document).changed.connect(self._variablesChange)
def html_copy(cursor, scheme='editor', number_lines=False): """Return a new QTextDocument with highlighting set as HTML textcharformats. The cursor is a cursor of a document.Document instance. If the cursor has a selection, only the selection is put in the new document. If number_lines is True, line numbers are added. """ data = textformats.formatData(scheme) doc = QTextDocument() doc.setDefaultFont(data.font) doc.setPlainText(cursor.document().toPlainText()) if metainfo.info(cursor.document()).highlighting: highlight(doc, mapping(data), ly.lex.state(documentinfo.mode(cursor.document()))) if cursor.hasSelection(): # cut out not selected text start, end = cursor.selectionStart(), cursor.selectionEnd() cur1 = QTextCursor(doc) cur1.setPosition(start, QTextCursor.KeepAnchor) cur2 = QTextCursor(doc) cur2.setPosition(end) cur2.movePosition(QTextCursor.End, QTextCursor.KeepAnchor) cur2.removeSelectedText() cur1.removeSelectedText() if number_lines: c = QTextCursor(doc) f = QTextCharFormat() f.setBackground(QColor('#eeeeee')) if cursor.hasSelection(): num = cursor.document().findBlock( cursor.selectionStart()).blockNumber() + 1 last = cursor.document().findBlock(cursor.selectionEnd()) else: num = 1 last = cursor.document().lastBlock() lastnum = last.blockNumber() + 1 padding = len(format(lastnum)) block = doc.firstBlock() while block.isValid(): c.setPosition(block.position()) c.setCharFormat(f) c.insertText('{0:>{1}d} '.format(num, padding)) block = block.next() num += 1 return doc
def showProgress(self, document): job = jobmanager.job(document) if job and job.is_running(): buildtime = metainfo.info(document).buildtime if not buildtime: buildtime = 3.0 + document.blockCount() / 20 # very arbitrary estimate... self._bar.start(buildtime, job.elapsed_time()) if jobattributes.get(job).hidden: self._bar.setEnabled(False) self._bar.setMaximumHeight(8) self._bar.setTextVisible(False) else: self._bar.setEnabled(True) self._bar.setMaximumHeight(14) self._bar.setTextVisible(True) else: self._bar.stop(False)
def html_copy(cursor, scheme="editor", number_lines=False): """Return a new QTextDocument with highlighting set as HTML textcharformats. The cursor is a cursor of a document.Document instance. If the cursor has a selection, only the selection is put in the new document. If number_lines is True, line numbers are added. """ data = textformats.formatData(scheme) doc = QTextDocument() doc.setDefaultFont(data.font) doc.setPlainText(cursor.document().toPlainText()) if metainfo.info(cursor.document()).highlighting: highlight(doc, mapping(data), ly.lex.state(documentinfo.mode(cursor.document()))) if cursor.hasSelection(): # cut out not selected text start, end = cursor.selectionStart(), cursor.selectionEnd() cur1 = QTextCursor(doc) cur1.setPosition(start, QTextCursor.KeepAnchor) cur2 = QTextCursor(doc) cur2.setPosition(end) cur2.movePosition(QTextCursor.End, QTextCursor.KeepAnchor) cur2.removeSelectedText() cur1.removeSelectedText() if number_lines: c = QTextCursor(doc) f = QTextCharFormat() f.setBackground(QColor("#eeeeee")) if cursor.hasSelection(): num = cursor.document().findBlock(cursor.selectionStart()).blockNumber() + 1 last = cursor.document().findBlock(cursor.selectionEnd()) else: num = 1 last = cursor.document().lastBlock() lastnum = last.blockNumber() + 1 padding = len(format(lastnum)) block = doc.firstBlock() while block.isValid(): c.setPosition(block.position()) c.setCharFormat(f) c.insertText("{0:>{1}d} ".format(num, padding)) block = block.next() num += 1 return doc
def keyPressEvent(self, ev): if homekey.handle(self, ev): return super(View, self).keyPressEvent(ev) if metainfo.info(self.document()).auto_indent: # run the indenter on Return or when the user entered a dedent token. import indent cursor = self.textCursor() if ev.text() == '\r' or (ev.text() in ('}', '#', '>') and indent.indentable(cursor)): with cursortools.compress_undo(cursor, True): indent.auto_indent_block(cursor.block()) # keep the cursor at the indent position on vertical move cursor = self.textCursor() pos = cursor.position() cursor.setPosition(cursor.block().position()) # move horizontal cursor.setPosition(pos) # move back to position self.setTextCursor(cursor)
def keyPressEvent(self, ev): """Reimplemented to perform actions after a key has been pressed. Currently handles: - indent change on Enter, }, # or > """ super(View, self).keyPressEvent(ev) if metainfo.info(self.document()).auto_indent: # run the indenter on Return or when the user entered a dedent token. import indent cursor = self.textCursor() if ev.text() == '\r' or (ev.text() in ('}', '#', '>') and indent.indentable(cursor)): indent.auto_indent_block(cursor.block()) # fix subsequent vertical moves cursor.setPosition(cursor.position()) self.setTextCursor(cursor)
def keyPressEvent(self, ev): """Reimplemented to perform actions after a key has been pressed. Currently handles: - indent change on Enter, }, # or > - update the tooltip info when Ctrl is pressed """ super(View, self).keyPressEvent(ev) if ev.key() == Qt.Key_Control and self.include_target: self.viewport().setCursor(Qt.PointingHandCursor) if metainfo.info(self.document()).auto_indent: # run the indenter on Return or when the user entered a dedent token. import indent cursor = self.textCursor() if ev.text() == '\r' or (ev.text() in ('}', '#', '>') and indent.indentable(cursor)): indent.auto_indent_block(cursor.block()) # fix subsequent vertical moves cursor.setPosition(cursor.position()) self.setTextCursor(cursor)
def storeCursor(self): """Stores our cursor position in the metainfo.""" metainfo.info(self.document()).position = self.textCursor().position()
def restoreCursor(self): """Places the cursor on the position saved in metainfo.""" cursor = QTextCursor(self.document()) cursor.setPosition(metainfo.info(self.document()).position) self.setTextCursor(cursor) QTimer.singleShot(0, self.ensureCursorVisible)
def cut_assign(cursor): """Cuts selected text and assigns it to a LilyPond variable.""" # ask the variable name name = inputdialog.getText( None, _("Cut and Assign"), _("Please enter the name for the variable to assign the selected " "text to:"), regexp="[A-Za-z]+") if not name: return cursortools.strip_selection(cursor) # determine state at cursor block = cursortools.block(cursor) state = tokeniter.state(block) for t in tokeniter.partition(cursor).left: state.follow(t) mode = "" for p in state.parsers(): if isinstance(p, ly.lex.lilypond.ParseInputMode): if isinstance(p, ly.lex.lilypond.ParseLyricMode): mode = " \\lyricmode" elif isinstance(p, ly.lex.lilypond.ParseChordMode): mode = " \\chordmode" elif isinstance(p, ly.lex.lilypond.ParseFigureMode): mode = " \\figuremode" elif isinstance(p, ly.lex.lilypond.ParseDrumMode): mode = " \\drummode" break # find insertion place: found = False while block.previous().isValid(): block = block.previous() state = tokeniter.state(block) if isinstance(state.parser(), ly.lex.lilypond.ParseGlobal): found = True break tokens = tokeniter.tokens(block) for t in tokens: if isinstance(t, ly.lex.lilypond.Name): found = True break elif not isinstance(t, (ly.lex.Space, ly.lex.Comment)): break if found: break insert = QTextCursor(block) text = cursor.selection().toPlainText() space = '\n' if '\n' in text else ' ' text = ''.join((name, ' =', mode, ' {', space, text, space, '}\n\n')) with cursortools.compress_undo(cursor): cursor.insertText('\\' + name) pos = insert.selectionStart() insert.insertText(text) if metainfo.info(cursor.document()).auto_indent: insert.setPosition(pos, QTextCursor.KeepAnchor) with cursortools.compress_undo(insert, True): indent.re_indent(insert)
def toggleHighlighting(self): doc = self.currentDocument() minfo = metainfo.info(doc) minfo.highlighting = not minfo.highlighting highlighter.highlighter(doc).setHighlighting(minfo.highlighting) self.updateOtherDocActions()
def toggleAuto_indent(self): minfo = metainfo.info(self.currentDocument()) minfo.auto_indent = not minfo.auto_indent self.updateOtherDocActions()
def jobFinished(self, document, job, success): if document == self.viewSpace().document(): self._bar.stop(success) if success: metainfo.info(document).buildtime = job.elapsed()
def jobFinished(self, document, job, success): if document == self.viewSpace().document(): self._bar.stop(success and not jobattributes.get(job).hidden) if success: metainfo.info(document).buildtime = job.elapsed_time()
def _resetHighlighting(self): """Switch highlighting on or off depending on saved metainfo.""" self.setHighlighting(metainfo.info(self.document()).highlighting)
def jobFinished(self, document, job, success): if document == self.viewSpace().document(): self._bar.stop(success and not jobattributes.get(job).hidden) if success: metainfo.info(document).buildtime = job.elapsed()