📄 qtextcontrol.cpp
字号:
doc = new QTextDocument(q); } QObject::connect(doc->documentLayout(), SIGNAL(update(QRectF)), q, SIGNAL(updateRequest(QRectF))); QObject::connect(doc->documentLayout(), SIGNAL(documentSizeChanged(QSizeF)), q, SIGNAL(documentSizeChanged(QSizeF))); cursor = QTextCursor(doc);// #### doc->documentLayout()->setPaintDevice(viewport); QObject::connect(doc, SIGNAL(contentsChanged()), q, SLOT(_q_updateCurrentCharFormatAndSelection())); QObject::connect(doc, SIGNAL(cursorPositionChanged(QTextCursor)), q, SLOT(_q_emitCursorPosChanged(QTextCursor))); // convenience signal forwards QObject::connect(doc, SIGNAL(contentsChanged()), q, SIGNAL(textChanged())); QObject::connect(doc, SIGNAL(undoAvailable(bool)), q, SIGNAL(undoAvailable(bool))); QObject::connect(doc, SIGNAL(redoAvailable(bool)), q, SIGNAL(redoAvailable(bool))); } bool previousUndoRedoState = doc->isUndoRedoEnabled(); doc->setUndoRedoEnabled(false); // avoid multiple textChanged() signals being emitted QObject::disconnect(doc, SIGNAL(contentsChanged()), q, SIGNAL(textChanged())); if (!text.isEmpty()) { // clear 'our' cursor for insertion to prevent // the emission of the cursorPositionChanged() signal. // instead we emit it only once at the end instead of // at the end of the document after loading and when // positioning the cursor again to the start of the // document. cursor = QTextCursor(); if (format == Qt::PlainText) { QTextCursor formatCursor(doc); // put the setPlainText and the setCharFormat into one edit block, // so that the syntax highlight triggers only /once/ for the entire // document, not twice. formatCursor.beginEditBlock(); doc->setPlainText(text); doc->setUndoRedoEnabled(false); formatCursor.select(QTextCursor::Document); formatCursor.setCharFormat(charFormatForInsertion); formatCursor.endEditBlock(); } else { doc->setHtml(text); doc->setUndoRedoEnabled(false); } cursor = QTextCursor(doc); } else if (clearDocument) { doc->clear(); cursor.movePosition(QTextCursor::Start); QTextBlockFormat blockFmt; blockFmt.setLayoutDirection(layoutDirection); cursor.mergeBlockFormat(blockFmt); } cursor.setCharFormat(charFormatForInsertion); QObject::connect(doc, SIGNAL(contentsChanged()), q, SIGNAL(textChanged())); emit q->textChanged(); doc->setUndoRedoEnabled(previousUndoRedoState); _q_updateCurrentCharFormatAndSelection(); doc->setModified(false); q->ensureCursorVisible(); emit q->cursorPositionChanged();}void QTextControlPrivate::startDrag(){#ifndef QT_NO_DRAGANDDROP Q_Q(QTextControl); mousePressed = false; if (!contextWidget) return; QMimeData *data = q->createMimeDataFromSelection(); QDrag *drag = new QDrag(contextWidget); drag->setMimeData(data); Qt::DropActions actions = Qt::CopyAction; if (interactionFlags & Qt::TextEditable) actions |= Qt::MoveAction; Qt::DropAction action = drag->exec(actions, Qt::MoveAction); if (action == Qt::MoveAction && drag->target() != contextWidget) cursor.removeSelectedText();#endif}void QTextControlPrivate::setCursorPosition(const QPointF &pos){ const int cursorPos = doc->documentLayout()->hitTest(pos, Qt::FuzzyHit); if (cursorPos == -1) return; cursor.setPosition(cursorPos);}void QTextControlPrivate::setCursorPosition(int pos, QTextCursor::MoveMode mode){ cursor.setPosition(pos, mode); if (mode != QTextCursor::KeepAnchor) { selectedWordOnDoubleClick = QTextCursor(); selectedLineOnDoubleClick = QTextCursor(); }}void QTextControlPrivate::repaintCursor(){ Q_Q(QTextControl); emit q->updateRequest(q->cursorRect());}void QTextControlPrivate::repaintOldAndNewSelection(const QTextCursor &oldSelection){ Q_Q(QTextControl); if (cursor.hasSelection() && oldSelection.hasSelection() && cursor.currentFrame() == oldSelection.currentFrame() && !cursor.hasComplexSelection() && !oldSelection.hasComplexSelection() && cursor.anchor() == oldSelection.anchor() && cursorIsFocusIndicator) { QTextCursor differenceSelection(doc); differenceSelection.setPosition(oldSelection.position()); differenceSelection.setPosition(cursor.position(), QTextCursor::KeepAnchor); emit q->updateRequest(q->selectionRect(differenceSelection)); } else { if (!oldSelection.isNull()) emit q->updateRequest(q->selectionRect(oldSelection)); emit q->updateRequest(q->selectionRect()); }}void QTextControlPrivate::selectionChanged(bool forceEmitSelectionChanged /*=false*/){ Q_Q(QTextControl); if (forceEmitSelectionChanged) emit q->selectionChanged(); bool current = cursor.hasSelection(); if (current == lastSelectionState) return; lastSelectionState = current; emit q->copyAvailable(current); if (!forceEmitSelectionChanged) emit q->selectionChanged(); emit q->microFocusChanged();}void QTextControlPrivate::_q_updateCurrentCharFormatAndSelection(){ updateCurrentCharFormat(); selectionChanged();}#ifndef QT_NO_CLIPBOARDvoid QTextControlPrivate::setClipboardSelection(){ QClipboard *clipboard = QApplication::clipboard(); if (!cursor.hasSelection() || !clipboard->supportsSelection()) return; Q_Q(QTextControl); QMimeData *data = q->createMimeDataFromSelection(); clipboard->setMimeData(data, QClipboard::Selection);}#endifvoid QTextControlPrivate::_q_emitCursorPosChanged(const QTextCursor &someCursor){ Q_Q(QTextControl); if (someCursor.isCopyOf(cursor)) { emit q->cursorPositionChanged(); emit q->microFocusChanged(); }}void QTextControlPrivate::setBlinkingCursorEnabled(bool enable){ Q_Q(QTextControl); if (enable && QApplication::cursorFlashTime() > 0) { cursorBlinkTimer.start(QApplication::cursorFlashTime() / 2, q); cursorOn = true; } else { cursorBlinkTimer.stop(); cursorOn = false; } repaintCursor();}void QTextControlPrivate::extendWordwiseSelection(int suggestedNewPosition, qreal mouseXPosition){ Q_Q(QTextControl); // if inside the initial selected word keep that if (suggestedNewPosition >= selectedWordOnDoubleClick.selectionStart() && suggestedNewPosition <= selectedWordOnDoubleClick.selectionEnd()) { q->setTextCursor(selectedWordOnDoubleClick); return; } QTextCursor curs = selectedWordOnDoubleClick; curs.setPosition(suggestedNewPosition, QTextCursor::KeepAnchor); if (!curs.movePosition(QTextCursor::StartOfWord)) return; const int wordStartPos = curs.position(); const int blockPos = curs.block().position(); const QPointF blockCoordinates = doc->documentLayout()->blockBoundingRect(curs.block()).topLeft(); QTextLine line = currentTextLine(curs); if (!line.isValid()) return; const qreal wordStartX = line.cursorToX(curs.position() - blockPos) + blockCoordinates.x(); if (!curs.movePosition(QTextCursor::EndOfWord)) return; const int wordEndPos = curs.position(); const QTextLine otherLine = currentTextLine(curs); if (otherLine.textStart() != line.textStart() || wordEndPos == wordStartPos) return; const qreal wordEndX = line.cursorToX(curs.position() - blockPos) + blockCoordinates.x(); if (mouseXPosition < wordStartX || mouseXPosition > wordEndX) return; // keep the already selected word even when moving to the left // (#39164) if (suggestedNewPosition < selectedWordOnDoubleClick.position()) cursor.setPosition(selectedWordOnDoubleClick.selectionEnd()); else cursor.setPosition(selectedWordOnDoubleClick.selectionStart()); const qreal differenceToStart = mouseXPosition - wordStartX; const qreal differenceToEnd = wordEndX - mouseXPosition; if (differenceToStart < differenceToEnd) setCursorPosition(wordStartPos, QTextCursor::KeepAnchor); else setCursorPosition(wordEndPos, QTextCursor::KeepAnchor); if (interactionFlags & Qt::TextSelectableByMouse) {#ifndef QT_NO_CLIPBOARD setClipboardSelection();#endif selectionChanged(true); }}void QTextControlPrivate::extendLinewiseSelection(int suggestedNewPosition){ Q_Q(QTextControl); // if inside the initial selected line keep that if (suggestedNewPosition >= selectedLineOnDoubleClick.selectionStart() && suggestedNewPosition <= selectedLineOnDoubleClick.selectionEnd()) { q->setTextCursor(selectedLineOnDoubleClick); return; } if (suggestedNewPosition < selectedLineOnDoubleClick.position()) { cursor.setPosition(selectedLineOnDoubleClick.selectionEnd()); cursor.setPosition(suggestedNewPosition, QTextCursor::KeepAnchor); cursor.movePosition(QTextCursor::StartOfLine, QTextCursor::KeepAnchor); } else { cursor.setPosition(selectedLineOnDoubleClick.selectionStart()); cursor.setPosition(suggestedNewPosition, QTextCursor::KeepAnchor); cursor.movePosition(QTextCursor::EndOfLine, QTextCursor::KeepAnchor); } if (interactionFlags & Qt::TextSelectableByMouse) {#ifndef QT_NO_CLIPBOARD setClipboardSelection();#endif selectionChanged(true); }}void QTextControlPrivate::_q_deleteSelected(){ if (!(interactionFlags & Qt::TextEditable) || !cursor.hasSelection()) return; cursor.removeSelectedText();}void QTextControl::undo(){ Q_D(QTextControl); d->doc->undo(&d->cursor); ensureCursorVisible();}void QTextControl::redo(){ Q_D(QTextControl); d->doc->redo(&d->cursor); ensureCursorVisible();}QTextControl::QTextControl(QObject *parent) : QObject(*new QTextControlPrivate, parent){ Q_D(QTextControl); d->init();}QTextControl::QTextControl(const QString &text, QObject *parent) : QObject(*new QTextControlPrivate, parent){ Q_D(QTextControl); d->init(Qt::RichText, text);}QTextControl::QTextControl(QTextDocument *doc, QObject *parent) : QObject(*new QTextControlPrivate, parent){ Q_D(QTextControl); d->init(Qt::RichText, QString(), doc);}QTextControl::~QTextControl(){}void QTextControl::setDocument(QTextDocument *document){ Q_D(QTextControl); if (d->doc == document) return; d->doc->disconnect(this); d->doc->documentLayout()->disconnect(this); d->doc->documentLayout()->setPaintDevice(0); if (d->doc->parent() == this) delete d->doc; d->doc = 0; d->setContent(Qt::RichText, QString(), document);}QTextDocument *QTextControl::document() const{ Q_D(const QTextControl); return d->doc;}void QTextControl::setTextCursor(const QTextCursor &cursor){ Q_D(QTextControl); const bool posChanged = cursor.position() != d->cursor.position(); const QTextCursor oldSelection = d->cursor; d->cursor = cursor; d->_q_updateCurrentCharFormatAndSelection(); ensureCursorVisible(); d->repaintOldAndNewSelection(oldSelection); if (posChanged) emit cursorPositionChanged();}QTextCursor QTextControl::textCursor() const{ Q_D(const QTextControl); return d->cursor;}#ifndef QT_NO_CLIPBOARDvoid QTextControl::cut(){ Q_D(QTextControl); if (!(d->interactionFlags & Qt::TextEditable) || !d->cursor.hasSelection()) return; copy(); d->cursor.removeSelectedText();}void QTextControl::copy(){ Q_D(QTextControl); if (!d->cursor.hasSelection()) return; QMimeData *data = createMimeDataFromSelection(); QApplication::clipboard()->setMimeData(data);}void QTextControl::paste(){ const QMimeData *md = QApplication::clipboard()->mimeData(); if (md) insertFromMimeData(md);}#endifvoid QTextControl::clear(){ Q_D(QTextControl); // clears and sets empty content d->setContent();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -