⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qtextbrowser.cpp

📁 qt-x11-opensource-src-4.1.4.tar.gz源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/******************************************************************************** Copyright (C) 1992-2006 Trolltech ASA. All rights reserved.**** This file is part of the QtGui module of the Qt Toolkit.**** This file may be used under the terms of the GNU General Public** License version 2.0 as published by the Free Software Foundation** and appearing in the file LICENSE.GPL included in the packaging of** this file.  Please review the following information to ensure GNU** General Public Licensing requirements will be met:** http://www.trolltech.com/products/qt/opensource.html**** If you are unsure which license is appropriate for your use, please** review the following information:** http://www.trolltech.com/products/qt/licensing.html or contact the** sales department at sales@trolltech.com.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.******************************************************************************/#include "qtextbrowser.h"#include "qtextedit_p.h"#ifndef QT_NO_TEXTBROWSER#include <qstack.h>#include <qapplication.h>#include <qevent.h>#include <qdesktopwidget.h>#include <qdebug.h>#include <qabstracttextdocumentlayout.h>#include "private/qtextdocumentlayout_p.h"#include <qtextcodec.h>#include <qpainter.h>#include <qdir.h>#include <qwhatsthis.h>#include <qtextobject.h>class QTextBrowserPrivate : public QTextEditPrivate{    Q_DECLARE_PUBLIC(QTextBrowser)public:    QTextBrowserPrivate()         : textOrSourceChanged(false), forceLoadOnSourceChange(false),          hadSelectionOnMousePress(false) {}    void init();    struct HistoryEntry {        QUrl url;        int hpos;        int vpos;    };    QStack<HistoryEntry> stack;    QStack<HistoryEntry> forwardStack;    QUrl home;    QUrl currentURL;    QStringList searchPaths;    /*flag necessary to give the linkClicked() signal some meaningful      semantics when somebody connected to it calls setText() or      setSource() */    bool textOrSourceChanged;    bool forceLoadOnSourceChange;#ifndef QT_NO_CURSOR    QCursor oldCursor;#endif    QString findFile(const QUrl &name) const;    inline void _q_documentModified()    {        textOrSourceChanged = true;        forceLoadOnSourceChange = true;    }    void activateAnchor(const QString &href);    void setSource(const QUrl &url);    bool findNextPrevAnchor(bool next, int &start, int &end);    QString anchorOnMousePress;    bool hadSelectionOnMousePress;#ifdef QT_KEYPAD_NAVIGATION    void keypadMove(bool next);    int lastPos;#endif};static bool isAbsoluteFileName(const QString &name){    return !name.isEmpty()           && (name[0] == '/'#if defined(Q_WS_WIN)               || (name[0].isLetter() && name[1] == QLatin1Char(':')) || name.startsWith("\\\\")#endif               || (name[0]  == QLatin1Char(':') && name[1] == QLatin1Char('/'))              );}QString QTextBrowserPrivate::findFile(const QUrl &name) const{    QString fileName;    if (name.scheme() == QLatin1String("qrc"))        fileName = QLatin1String(":/") + name.path();    else        fileName = name.toLocalFile();    if (isAbsoluteFileName(fileName))        return fileName;    QString slash("/");    foreach (QString path, searchPaths) {        if (!path.endsWith(slash))            path.append(slash);        path.append(fileName);        if (QFileInfo(path).isReadable())            return path;    }    if (stack.isEmpty())        return fileName;    QFileInfo path(QFileInfo(currentURL.toLocalFile()).absolutePath(), fileName);    return path.absoluteFilePath();}void QTextBrowserPrivate::activateAnchor(const QString &href){    if (href.isEmpty())        return;    Q_Q(QTextBrowser);    textOrSourceChanged = false;    const QUrl url = isAbsoluteFileName(currentURL.toLocalFile())                     ? currentURL.resolved(href) : QUrl(href);    emit q->anchorClicked(url);    if (!textOrSourceChanged)        q->setSource(url);}void QTextBrowserPrivate::setSource(const QUrl &url){    Q_Q(QTextBrowser);#ifndef QT_NO_CURSOR    if (q->isVisible())        qApp->setOverrideCursor(Qt::WaitCursor);#endif    textOrSourceChanged = true;    QString txt;    bool doSetText = false;    QUrl currentUrlWithoutFragment = currentURL;    currentUrlWithoutFragment.setFragment(QString());    QUrl newUrlWithoutFragment = currentURL.resolved(url);    newUrlWithoutFragment.setFragment(QString());    if (url.isValid()        && (newUrlWithoutFragment != currentUrlWithoutFragment || forceLoadOnSourceChange)) {        QVariant data = q->loadResource(QTextDocument::HtmlResource, url);        if (data.type() == QVariant::String) {            txt = data.toString();        } else if (data.type() == QVariant::ByteArray) {#ifndef QT_NO_TEXTCODEC            QByteArray ba = data.toByteArray();            QTextCodec *codec = Qt::codecForHtml(ba);            txt = codec->toUnicode(ba);#else	    txt = data.toString();#endif        }        if (txt.isEmpty())            qWarning("QTextBrowser: no document for %s", url.toString().toLatin1().constData());        if (q->isVisible()) {            QString firstTag = txt.left(txt.indexOf('>') + 1);            if (firstTag.left(3) == "<qt" && firstTag.contains("type") && firstTag.contains("detail")) {#ifndef QT_NO_CURSOR                qApp->restoreOverrideCursor();#endif#ifndef QT_NO_WHATSTHIS                QWhatsThis::showText(QCursor::pos(), txt, q);#endif                return;            }        }        currentURL = currentURL.resolved(url);        doSetText = true;    }    if (!home.isValid())        home = url;    if (doSetText)        q->QTextEdit::setHtml(txt);    forceLoadOnSourceChange = false;    if (!url.fragment().isEmpty()) {        q->scrollToAnchor(url.fragment());    } else {        hbar->setValue(0);        vbar->setValue(0);    }#ifndef QT_NO_CURSOR    if (q->isVisible())        qApp->restoreOverrideCursor();#endif    emit q->sourceChanged(url);}bool QTextBrowserPrivate::findNextPrevAnchor(bool next, int &start, int &end){    if (!focusIndicator.hasSelection()) {        focusIndicator = QTextCursor(doc);        if (next)            focusIndicator.movePosition(QTextCursor::Start);        else            focusIndicator.movePosition(QTextCursor::End);    }    Q_ASSERT(!focusIndicator.isNull());    int anchorStart = -1;    int anchorEnd = -1;    if (next) {        const int startPos = focusIndicator.selectionEnd();        QTextBlock block = doc->findBlock(startPos);        QTextBlock::Iterator it = block.begin();        while (!it.atEnd() && it.fragment().position() < startPos)            ++it;        while (block.isValid()) {            anchorStart = -1;            // find next anchor            for (; !it.atEnd(); ++it) {                const QTextFragment fragment = it.fragment();                const QTextCharFormat fmt = fragment.charFormat();                if (fmt.isAnchor() && fmt.hasProperty(QTextFormat::AnchorHref)) {                    anchorStart = fragment.position();                    break;                }            }            if (anchorStart != -1) {                anchorEnd = -1;                // find next non-anchor fragment                for (; !it.atEnd(); ++it) {                    const QTextFragment fragment = it.fragment();                    const QTextCharFormat fmt = fragment.charFormat();                    if (!fmt.isAnchor()) {                        anchorEnd = fragment.position();                        break;                    }                }                if (anchorEnd == -1)                    anchorEnd = block.position() + block.length() - 1;                // make found selection                break;            }            block = block.next();            it = block.begin();        }    } else {        int startPos = focusIndicator.selectionStart();        if (startPos > 0)            --startPos;        QTextBlock block = doc->findBlock(startPos);        QTextBlock::Iterator blockStart = block.begin();        QTextBlock::Iterator it = block.end();        if (startPos == block.position()) {            it = block.begin();        } else {            do {                if (it == blockStart) {                    it = QTextBlock::Iterator();                    block = QTextBlock();                } else {                    --it;                }            } while (!it.atEnd() && it.fragment().position() + it.fragment().length() - 1 > startPos);        }        while (block.isValid()) {            anchorStart = -1;            if (!it.atEnd()) {                do {                    const QTextFragment fragment = it.fragment();                    const QTextCharFormat fmt = fragment.charFormat();                    if (fmt.isAnchor() && fmt.hasProperty(QTextFormat::AnchorHref)) {                        anchorStart = fragment.position() + fragment.length();                        break;                    }                    if (it == blockStart)                        it = QTextBlock::Iterator();                    else                        --it;                } while (!it.atEnd());            }            if (anchorStart != -1 && !it.atEnd()) {                anchorEnd = -1;                do {                    const QTextFragment fragment = it.fragment();                    const QTextCharFormat fmt = fragment.charFormat();                    if (!fmt.isAnchor()) {                        anchorEnd = fragment.position() + fragment.length();                        break;                    }                    if (it == blockStart)                        it = QTextBlock::Iterator();                    else                        --it;                } while (!it.atEnd());                if (anchorEnd == -1)                    anchorEnd = qMax(0, block.position());                break;            }            block = block.previous();            it = block.end();            if (it != block.begin())                --it;            blockStart = block.begin();        }    }    if (anchorStart != -1 && anchorEnd != -1) {        start = anchorStart;        end = anchorEnd;        return true;    }        return false;}#ifdef QT_KEYPAD_NAVIGATIONvoid QTextBrowserPrivate::keypadMove(bool next){    Q_Q(QTextBrowser);    const int height = viewport->height();    int anchorStart, anchorEnd;    if (findNextPrevAnchor(next, anchorStart, anchorEnd)) {        QTextBlock block = doc->findBlock(next ? anchorEnd : anchorStart);        const int yOffset = vbar->value();        const int cursYOffset = (int)block.layout()->position().y();        const int overlap = 20;        if (next) {            if (cursYOffset > yOffset + height) {                vbar->setValue(yOffset + height - overlap);                if (cursYOffset > vbar->value() + height) {                    emit q->highlighted(QUrl());                    emit q->highlighted(QString());                    return;                }            } else if (cursYOffset < yOffset) {                if (yOffset < vbar->maximum())                    vbar->setValue(yOffset + height - overlap);                else                    vbar->setValue(0);                emit q->highlighted(QUrl());                emit q->highlighted(QString());                return;            }        } else {            qDebug("found anchor");            if (cursYOffset < yOffset) {                qDebug("1");                vbar->setValue(yOffset - height + overlap);                if (cursYOffset < vbar->value()) {                    emit q->highlighted(QUrl());                    emit q->highlighted(QString());                    return;                }            } else if (cursYOffset > yOffset + height) {                qDebug("2");                if (yOffset > 0)                    vbar->setValue(yOffset - height + overlap);                else                    vbar->setValue(vbar->maximum());                emit q->highlighted(QUrl());                emit q->highlighted(QString());                return;            }        }        focusIndicator.setPosition(anchorStart);                if(next)            focusIndicator.setPosition(anchorEnd, QTextCursor::KeepAnchor);                QTextCharFormat charFmt;        charFmt = focusIndicator.charFormat();        emit q->highlighted(QUrl(charFmt.anchorHref()));        emit q->highlighted(charFmt.anchorHref());                if(!next)            focusIndicator.setPosition(anchorEnd, QTextCursor::KeepAnchor);    } else {        const int yOffset = vbar->value();        const int overlap = 20;        if (next) {            if (yOffset == vbar->maximum())                vbar->setValue(0);            else                vbar->setValue(yOffset + height - overlap);        } else {            if (yOffset == 0)                vbar->setValue(vbar->maximum());            else                vbar->setValue(yOffset - height + overlap);        }        focusIndicator.clearSelection();                emit q->highlighted(QUrl());        emit q->highlighted(QString());    }    if (focusIndicator.hasSelection()) {        qSwap(focusIndicator, cursor);        q->ensureCursorVisible();        qSwap(focusIndicator, cursor);        viewport->update();    } else {        viewport->update();    }}#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. The contents of QTextEdit are set with    setHtml() or setPlainText(), but QTextBrowser also implements the    setSource() function, making it possible to set the text to a named    document. 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.    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 provide your users with editable rich text 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.    If you want to load documents stored in the Qt resource system use    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*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -