📄 qtextbrowser.cpp
字号:
focusedPos = scrollYOffset; focusIt = true; } else { // This is the "normal" case - no scroll bar adjustments, no large anchors, // and no wrapping. foundNextAnchor = control->findNextPrevAnchor(prevFocus, next, anchorToFocus); } } // If not found yet, see if we need to wrap if (!focusIt && !foundNextAnchor) { if (next) { if (yOffset == vbar->maximum()) { prevFocus.movePosition(QTextCursor::Start); yOffset = scrollYOffset = 0; // Refresh the rectangles viewRect = QRectF(0, yOffset, control->size().width(), height); newViewRect = QRectF(0, scrollYOffset, control->size().width(), height); bothViewRects = viewRect.united(newViewRect); } } else { if (yOffset == 0) { prevFocus.movePosition(QTextCursor::End); yOffset = scrollYOffset = vbar->maximum(); // Refresh the rectangles viewRect = QRectF(0, yOffset, control->size().width(), height); newViewRect = QRectF(0, scrollYOffset, control->size().width(), height); bothViewRects = viewRect.united(newViewRect); } } // Try looking now foundNextAnchor = control->findNextPrevAnchor(prevFocus, next, anchorToFocus); } // If we did actually find an anchor to use... if (foundNextAnchor) { QRectF desiredRect = control->selectionRect(anchorToFocus); // XXX This is an arbitrary heuristic // Decide to focus an anchor if it will be at least be // in the middle region of the screen after a scroll. // This can result in partial anchors with focus, but // insisting on links being completely visible before // selecting them causes disparities between links that // take up 90% of the screen height and those that take // up e.g. 110% // Obviously if a link is entirely visible, we still // focus it. if(bothViewRects.contains(desiredRect) || bothViewRects.adjusted(0, visibleLinkAmount, 0, -visibleLinkAmount).intersects(desiredRect)) { focusIt = true; // We aim to put the new link in the middle of the screen, // unless the link is larger than the screen (we just move to // display the first page of the link) if (desiredRect.height() > height) { if (next) focusedPos = (int) desiredRect.top(); else focusedPos = (int) desiredRect.bottom() - height; } else focusedPos = (int) ((desiredRect.top() + desiredRect.bottom()) / 2 - (height / 2)); // and clamp it to make sure we don't skip content. if (next) focusedPos = qBound(yOffset, focusedPos, scrollYOffset); else focusedPos = qBound(scrollYOffset, focusedPos, yOffset); } } // If we didn't get a new anchor, check if the old one is still on screen when we scroll // Note that big (larger than screen height) anchors also have some handling at the // start of this function. if (!focusIt && prevFocus.hasSelection()) { QRectF desiredRect = control->selectionRect(prevFocus); // XXX this may be better off also using the visibleLinkAmount value if(newViewRect.intersects(desiredRect)) { focusedPos = scrollYOffset; focusIt = true; anchorToFocus = prevFocus; } } // setTextCursor ensures that the cursor is visible. save & restore // the scroll bar values therefore const int savedXOffset = hbar->value(); // Now actually process our decision if (focusIt && control->setFocusToAnchor(anchorToFocus)) { // Save the focus for next time prevFocus = control->textCursor(); // Scroll vbar->setValue(focusedPos); lastKeypadScrollValue = focusedPos; hbar->setValue(savedXOffset); // Ensure that the new selection is highlighted. const QString href = control->anchorAtCursor(); QUrl url = resolveUrl(href); emit q->highlighted(url); emit q->highlighted(url.toString()); } else { // Scroll vbar->setValue(scrollYOffset); lastKeypadScrollValue = scrollYOffset; // now make sure we don't have a focused anchor QTextCursor cursor = control->textCursor(); cursor.clearSelection(); control->setTextCursor(cursor); hbar->setValue(savedXOffset); vbar->setValue(scrollYOffset); emit q->highlighted(QUrl()); emit q->highlighted(QString()); }}#endifQTextBrowserPrivate::HistoryEntry QTextBrowserPrivate::createHistoryEntry() const{ HistoryEntry entry; entry.url = q_func()->source(); entry.hpos = hbar->value(); entry.vpos = vbar->value(); const QTextCursor cursor = control->textCursor(); if (control->cursorIsFocusIndicator() && cursor.hasSelection()) { entry.focusIndicatorPosition = cursor.position(); entry.focusIndicatorAnchor = cursor.anchor(); } return entry;}void QTextBrowserPrivate::restoreHistoryEntry(const HistoryEntry entry){ setSource(entry.url); hbar->setValue(entry.hpos); vbar->setValue(entry.vpos); if (entry.focusIndicatorAnchor != -1 && entry.focusIndicatorPosition != -1) { QTextCursor cursor(control->document()); cursor.setPosition(entry.focusIndicatorAnchor); cursor.setPosition(entry.focusIndicatorPosition, QTextCursor::KeepAnchor); control->setCursorIsFocusIndicator(true); control->setTextCursor(cursor); }#ifdef QT_KEYPAD_NAVIGATION lastKeypadScrollValue = vbar->value(); prevFocus = control->textCursor(); #endif }/*! \class QTextBrowser qtextbrowser.h \brief The QTextBrowser class provides a rich text browser with hypertext navigation. \ingroup text This class extends QTextEdit (in read-only mode), adding some navigation functionality so that users can follow links in hypertext documents. If you want to provide your users with an editable rich text editor, use QTextEdit. If you want a text browser without hypertext navigation use QTextEdit, and use QTextEdit::setReadOnly() to disable editing. If you just need to display a small piece of rich text use QLabel. \section1 Document Source and Contents The contents of QTextEdit are set with setHtml() or setPlainText(), but QTextBrowser also implements the setSource() function, making it possible to use a named document as the source text. The name is looked up in a list of search paths and in the directory of the current document factory. If a document name ends with an anchor (for example, "\c #anchor"), the text browser automatically scrolls to that position (using scrollToAnchor()). When the user clicks on a hyperlink, the browser will call setSource() itself with the link's \c href value as argument. You can track the current source by connecting to the sourceChanged() signal. \section1 Navigation QTextBrowser provides backward() and forward() slots which you can use to implement Back and Forward buttons. The home() slot sets the text to the very first document displayed. The anchorClicked() signal is emitted when the user clicks an anchor. To override the default navigation behavior of the browser, call the setSource() function to supply new document text in a slot connected to this signal. If you want to load documents stored in the Qt resource system use \c{qrc} as the scheme in the URL to load. For example, for the document resource path \c{:/docs/index.html} use \c{qrc:/docs/index.html} as the URL with setSource(). \sa QTextEdit, QTextDocument*//*! \property QTextBrowser::modified \brief whether the contents of the text browser have been modified*//*! \property QTextBrowser::readOnly \brief whether the text browser is read-only*//*! \property QTextBrowser::undoRedoEnabled \brief whether the text browser supports undo/redo operations*/void QTextBrowserPrivate::init(){ Q_Q(QTextBrowser); control->setTextInteractionFlags(Qt::TextBrowserInteraction);#ifndef QT_NO_CURSOR viewport->setCursor(oldCursor);#endif q->setUndoRedoEnabled(false); viewport->setMouseTracking(true); QObject::connect(q->document(), SIGNAL(contentsChanged()), q, SLOT(_q_documentModified())); QObject::connect(control, SIGNAL(linkActivated(QString)), q, SLOT(_q_activateAnchor(QString))); QObject::connect(control, SIGNAL(linkHovered(QString)), q, SLOT(_q_highlightLink(QString)));}/*! Constructs an empty QTextBrowser with parent \a parent.*/QTextBrowser::QTextBrowser(QWidget *parent) : QTextEdit(*new QTextBrowserPrivate, parent){ Q_D(QTextBrowser); d->init();}#ifdef QT3_SUPPORT/*! Use one of the constructors that doesn't take the \a name argument and then use setObjectName() instead.*/QTextBrowser::QTextBrowser(QWidget *parent, const char *name) : QTextEdit(*new QTextBrowserPrivate, parent){ setObjectName(QString::fromAscii(name)); Q_D(QTextBrowser); d->init();}#endif/*! \internal*/QTextBrowser::~QTextBrowser(){}/*! \property QTextBrowser::source \brief the name of the displayed document. This is a an invalid url if no document is displayed or if the source is unknown. When setting this property QTextBrowser tries to find a document with the specified name in the paths of the searchPaths property and directory of the current source, unless the value is an absolute file path. It also checks for optional anchors and scrolls the document accordingly If the first tag in the document is \c{<qt type=detail>}, the document is displayed as a popup rather than as new document in the browser window itself. Otherwise, the document is displayed normally in the text browser with the text set to the contents of the named document with setHtml().*/QUrl QTextBrowser::source() const{ Q_D(const QTextBrowser); if (d->stack.isEmpty()) return QUrl(); else return d->stack.top().url;}/*! \property QTextBrowser::searchPaths \brief the search paths used by the text browser to find supporting content QTextBrowser uses this list to locate images and documents.*/QStringList QTextBrowser::searchPaths() const{ Q_D(const QTextBrowser); return d->searchPaths;}void QTextBrowser::setSearchPaths(const QStringList &paths){ Q_D(QTextBrowser); d->searchPaths = paths;}/*! Reloads the current set source.*/void QTextBrowser::reload(){ Q_D(QTextBrowser); QUrl s = d->currentURL; d->currentURL = QUrl(); setSource(s);}void QTextBrowser::setSource(const QUrl &url){ Q_D(QTextBrowser); const QTextBrowserPrivate::HistoryEntry historyEntry = d->createHistoryEntry(); d->setSource(url); if (!url.isValid()) return; // the same url you are already watching? if (!d->stack.isEmpty() && d->stack.top().url == url) return; if (!d->stack.isEmpty()) d->stack.top() = historyEntry; QTextBrowserPrivate::HistoryEntry entry; entry.url = url; entry.hpos = 0; entry.vpos = 0; d->stack.push(entry); emit backwardAvailable(d->stack.count() > 1); if (!d->forwardStack.isEmpty() && d->forwardStack.top().url == url) { d->forwardStack.pop(); emit forwardAvailable(d->forwardStack.count() > 0); } else { d->forwardStack.clear(); emit forwardAvailable(false); }}/*! \fn void QTextBrowser::backwardAvailable(bool available) This signal is emitted when the availability of backward() changes. \a available is false when the user is at home(); otherwise it is true.*//*! \fn void QTextBrowser::forwardAvailable(bool available) This signal is emitted when the availability of forward() changes. \a available is true after the user navigates backward() and false when the user navigates or goes forward().*//*! \fn void QTextBrowser::sourceChanged(const QUrl &src)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -