Qt SVG中的远程图像?

时间:2016-12-10 00:51:16

标签: qt svg

如何在SVG中包含来自互联网的图像Qt将显示?
我一直收到错误:

couldn't create image from  "http://www.colorwiki.com/images/2/22/Lindbloom.jpg"

SVG:

<svg width="100%" height="100%" viewBox="0 0 100 100"
     xmlns="http://www.w3.org/2000/svg"
     xmlns:xlink="http://www.w3.org/1999/xlink">
  <image xlink:href="http://www.colorwiki.com/images/2/22/Lindbloom.jpg" x="0" y="0"
      height="100" width="100" />
</svg>

如果图像是本地图像,则可以正常工作 - 它只能用于远程图像。

1 个答案:

答案 0 :(得分:0)

您必须重写从QtextBrowser继承的Class,以下是我的解决方案: 头文件:

#ifndef QHTMLBROWSER_H
#define QHTMLBROWSER_H 

#include <QtNetwork/QtNetwork>
#include <QTextBrowser>
#include <QTextDocument>
#include <QHash>
#include <QRegExp>
#include <QCryptographicHash>
#include <QApplication>

class QHtmlBrowser : public QTextBrowser
{
    Q_OBJECT
public:
    explicit QHtmlBrowser(QWidget *parent=0);
    ~QHtmlBrowser();

    void load(const QString &strHtml);
    void addResource(const QString& key, const QByteArray& bytes);
    void showHtml(const QString& strHtml, int timeoutSeconds);

signals:
    void loadFinished();

private:
    QString mHtml;
    QHash<QString, QByteArray> mResources;

public slots:
    void onLoadFinished();


};

#endif // QHTMLBROWSER_H

Cpp文件:

#include "qhtmlbrowser.h"
#include <QtGui/QVBoxLayout>
#include "globalsetting.h"
/*only provide the function GlobalSetting::getServer(),
   full url like :  http://www.colorwiki.com
*/


#define hit_ext(p) \
    else if (src.endsWith(#p, Qt::CaseInsensitive)) \
        ext = #p

#define index_tag   "question"
#define images_tag   "http://"

QString setUrl(QUrl& parentUrl, const QString& path)
{
    QString srcUrl;
    QString hostPath = parentUrl.host();
    if (parentUrl.port() != 80 && parentUrl.port()>0)
        hostPath += ":" + QString::number(parentUrl.port());
    hostPath += parentUrl.path();
    int pos = hostPath.lastIndexOf('/');
    if (pos > -1)
        hostPath = hostPath.left(pos);
    srcUrl = hostPath + "/" + path;
    while (srcUrl.contains("//"))
        srcUrl.replace("//", "/");
    srcUrl = "http://" + srcUrl;
    return srcUrl;
}


/*
 Because the Qtextbrowser only support the simple width=**, height=**, not support the 
style="width:**px;height:**px", this function to change the style format.
*/
QString formatStyle(QString sStyle)
{
    QStringList stylelist = sStyle.split(";");
    QRegExp rx("(\\d+)");  // match digit.
    QString s_result;
    foreach(QString st , stylelist)
    {
        int pos=0;
        QString temp;
        QString str = st.toLower();
        while ((pos = rx.indexIn(str, pos)) != -1) {
            temp=rx.cap(0);
            pos += rx.matchedLength();
        }

        if (str.contains("width"))
        {
            s_result = s_result+ " "+"width="+temp+" ";
        }else if (str.contains("height"))
        {
            s_result = s_result+ " "+"height="+temp+" ";
        }
    }

    return s_result;
}

void showQuestion(QHtmlBrowser *browser, const QString& strHtml, int timeoutSeconds)
{
    browser->showHtml(strHtml, timeoutSeconds);
}

void QHtmlBrowser::showHtml(const QString& strHtml, int timeoutSeconds)
{
    QNetworkAccessManager network;
    QNetworkRequest request;
    QByteArray requestContent;
    bool timeout;
    QUrl url(GlobalSetting::getServer());
    QString content = strHtml;

    //QRegExp imgTagRegex("\\<img[^\\>]*src\\s*=\\s*\"([^\"]*)\"[^\\>]*\\>", Qt::CaseInsensitive);
    QRegExp imgTagRegex("\\<img[^\\>]*src\\s*=\\s*\"([^\"]*)\"[^\\>]*style\\s*=\\s*\"([^\"]*)\"[^\\>]*\\>", Qt::CaseInsensitive);
    imgTagRegex.setMinimal(true);
    QStringList imgSrcList;
    QStringList imgTagList;
    QStringList imgStyleList;
    int offset = 0;
    QString s_test;
    while( (offset = imgTagRegex.indexIn(content, offset)) != -1){
                offset += imgTagRegex.matchedLength();
                imgTagList.append(imgTagRegex.cap(0));
                imgSrcList.append(imgTagRegex.cap(1));
                imgStyleList.append(imgTagRegex.cap(2));
      }

    QString srcUrl;
    //QString resourcePrefix(GlobalSetting::g_server);
    QString ext;
    int index = -1;
    QDateTime stamp;
    foreach(QString src, imgSrcList)
    {
        index++;
        srcUrl.clear();
        if (src.startsWith("http://", Qt::CaseInsensitive))
            srcUrl = src;
        else
        {
            if (0){}
                hit_ext(.png);
                hit_ext(.jpeg);
                hit_ext(.jpg);
                hit_ext(.gif);
                hit_ext(.svg);
                else continue;
                if (src.startsWith("://") || src.startsWith("file://", Qt::CaseInsensitive)) continue;
                srcUrl = setUrl(url, src);
                request.setUrl(srcUrl);
                requestContent = srcUrl.toUtf8();
                request.setHeader(QNetworkRequest::ContentLengthHeader, requestContent.length());
                //QCryptographicHash hash(QCryptographicHash::Md5);
                if (QNetworkReply* reply = network.get(request))
                {
                    timeout = false;
                    stamp = QDateTime::currentDateTime();
                    while (reply->isRunning())
                    {
                        QApplication::processEvents();
                        if (stamp.secsTo(QDateTime::currentDateTime()) > timeoutSeconds)
                        {
                             reply->abort();
                             timeout = true;
                             break;
                        }
                    }
                    if (timeout)
                    {
                         delete reply;
                         continue;
                    }
                    /*
                    // give up crypt the link of image src for speed up the display in embedded system.
                    QString imgFile = resourcePrefix + "/";

                    hash.addData(srcUrl.toUtf8());
                    foreach(char c, hash.result())
                    {
                        int cInt = (int)c;
                        if (cInt < 10)
                            imgFile += "0" + QString::number(cInt, 16).left(1);
                        else
                            imgFile += QString::number(cInt, 16).left(2);
                    }
                    imgFile += ext;
                    */
                    QString target = imgTagList[index];
                    QString style = imgStyleList[index];
                    if(target.contains("style"))
                    {
                        int istart=target.indexOf("style");
                        int iend = target.indexOf(style)+style.size();
                        QString fstyle = target.mid(istart, iend-istart+1);
                        target.replace(fstyle, formatStyle(style));
                    }

                    //target.replace(src, imgFile);
                    target.replace(src, srcUrl);
                    //addResource(imgFile, reply->readAll());
                    addResource(srcUrl, reply->readAll());
                    content.replace(imgTagList[index], target);
                    delete reply;
               }
         }
    }
    addResource(index_tag, content.toUtf8());

    emit loadFinished();
}

void QHtmlBrowser::onLoadFinished()
{
    QTextDocument* document = new QTextDocument(this);
    if (mResources.contains(index_tag))
    {
        foreach(QString key, mResources.keys())
        {
            if (key.startsWith(images_tag))
            {
                document->addResource(QTextDocument::ImageResource, key, QVariant(mResources[key]));
                //document->adjustSize();

            }
        }
        document->setHtml(QString::fromUtf8(mResources[index_tag]));
        //this->setLineWrapColumnOrWidth(200);
        this->setDocument(document);

    }
}

QHtmlBrowser::QHtmlBrowser(QWidget *parent)
    :QTextBrowser(parent)
{
    this->setReadOnly(true);
    //this->setLineWrapColumnOrWidth();
    this->setContextMenuPolicy(Qt::NoContextMenu);
    this->setAcceptRichText(true);
    this->setAutoFormatting(QTextEdit::AutoAll);
    connect(this, SIGNAL(loadFinished()), SLOT(onLoadFinished()));
}

QHtmlBrowser::~QHtmlBrowser()
{
}

void QHtmlBrowser::load(const QString &strHtml)
{
    mHtml = strHtml;
    QtConcurrent::run(showQuestion, this, strHtml, 30);
}

void QHtmlBrowser::addResource(const QString &key, const QByteArray &bytes)
{
    if (mResources.contains(key))
        mResources[key] = bytes;
    else
        mResources.insert(key, bytes);
}

以下是示例快照显示: enter image description here