Russian Qt Forum
Март 29, 2024, 05:36 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Реализация QNetworkReply для QWebView  (Прочитано 3865 раз)
Krizis
Гость
« : Июль 22, 2016, 12:43 »

Есть задача вернуть в веб QWebView ответ на запрос, отправленный в обход qt. Подменил QNetworkReply своим, в основном позаимствованным с просторов инета. код прилагается.


Код:
#include <QNetworkReply>
 #include <QWebSecurityOrigin>
#include <qcoreapplication.h>
#include <QtCore/QMetaObject>

class ProxyNetworkReply: public QNetworkReply
{
    Q_OBJECT

public:
    ProxyNetworkReply(QObject *parent, const QNetworkRequest &req,
            const QNetworkAccessManager::Operation op)
        : QNetworkReply(parent)
    {
        setRequest(req);
        setUrl(req.url());
        setOperation(op);

        setFinished(true);

        QNetworkReply::open(QIODevice::ReadOnly | QIODevice::Unbuffered);

        QString string = "<!DOCTYPE HTML><html> <head>  </head> <body><H1> description</H1></body></html>";

        m_content = string.toUtf8();
        m_lOffset = 0;

        setHeader(QNetworkRequest::ContentTypeHeader,
                QVariant("text/html; charset=UTF-8"));
        setHeader(QNetworkRequest::ContentLengthHeader,
                QVariant(m_content.size()));

        QMetaObject::invokeMethod(this, "metaDataChanged",
                Qt::QueuedConnection);
        QMetaObject::invokeMethod(this, "downloadProgress",
                Qt::QueuedConnection, Q_ARG(qint64, m_content.size()), Q_ARG(qint64, m_content.size()));
        QMetaObject::invokeMethod(this, "readyRead",
                Qt::QueuedConnection);

        QMetaObject::invokeMethod(this, "readChannelFinished",
                Qt::QueuedConnection);

        QMetaObject::invokeMethod(this, "finished",
                Qt::QueuedConnection);

            QCoreApplication::postEvent(this, new QEvent(QEvent::NetworkReplyUpdated));
    }
    void abort() { QNetworkReply::close(); }
    qint64 bytesAvailable() const { return m_content.size() - m_lOffset; }
    bool isSequential() const { return true; }

    qint64 size() const
    {
        return  m_content.size();
    }

protected:
    qint64 readData(char* pData, qint64 lMaxSize)
    {
        if (m_lOffset >= m_content.size())
            return -1;

        qint64 lCount = qMin(lMaxSize, m_content.size() - m_lOffset);
        memcpy(pData, m_content.constData() + m_lOffset, lCount);
        m_lOffset += lCount;
        return lCount;
    }

private slots:

private:
    QByteArray m_content;
    qint64 m_lOffset;
};

Сигналы вызываются, readData, тоже.  однако, страница браузера остаётся пустой.
Может кто нибудь подсказать, чего не хватает приведённой выше тестовой реализации? или , может, есть подсказка, как заставить QWebView отображать полученное?
Исходники смотре, может что пропустил, но вроде бы все нужные сигналы вызываются.

« Последнее редактирование: Июль 22, 2016, 12:47 от Krizis » Записан
gil9red
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 1805



Просмотр профиля WWW
« Ответ #1 : Июль 22, 2016, 12:48 »

А вы не пробовали логировать внутри методов? Может они вообще не вызываются
Записан

Bepec
Гость
« Ответ #2 : Июль 22, 2016, 13:07 »

На мой взгляд вы творите что то страшное. Вы лезете в нутро, непонятным образом пытаетесь имитировать работу QNetworkReply, так что мне непонятно что вы хотите получить.

PS одни сигналы в контрукторе чего стоят. Они скорее всего уходят в никуда, ибо при создании reply ещё никуда не подключено и подцепиться к сигналам вы времени не даёте Улыбающийся
Записан
Krizis
Гость
« Ответ #3 : Июль 22, 2016, 14:26 »

Сигналы срабатывают, т.е. внешние подписчики их получают. В частности, управляющий всем этим хозяйством виджет по сигналу "onfinish"  прокручивает прогрессбар.
Проблема действительно в том, что я не очень представляю, что и зачем в этом объекте. Более - менее уловил основную идею. Если б сам раньше подходил к транспорту с такой архитектурой, может было бы проще.

Пока пытаюсь в обход засовывать полученный код и ответа через setContent.

Что страшного я собираюсь сделать: передавать запрос по своему протоколу через специализированный прокси. Для этого формирую тело запроса из полей QNetworkAccessManager::createRequest
Ответ приходится давать в виде своей реализации QNetworkReply. Код выше - конечно тестовый,  в реальном варианте все сигналы должны активироваться в передаче данных в QNetworkReply от внешнего транспорта.
Записан
Krizis
Гость
« Ответ #4 : Июль 22, 2016, 14:27 »

А вы не пробовали логировать внутри методов? Может они вообще не вызываются

Смотрел бряками, вызывается bytesAvailable, readData,  abort. В таком порядке.
Записан
Bepec
Гость
« Ответ #5 : Июль 22, 2016, 14:39 »

Зачем вам такие проблемы?
Сделайте приём нормальный на стороне прокси, а там уже создавайте какой вам нужно пакет.

Просто вы взяли и разобрали мотор, а на деле вам нужно топливо поменять. Смысла не вижу Улыбающийся
Записан
Krizis
Гость
« Ответ #6 : Июль 22, 2016, 14:55 »

Зачем вам такие проблемы?
Сделайте приём нормальный на стороне прокси, а там уже создавайте какой вам нужно пакет.

Просто вы взяли и разобрали мотор, а на деле вам нужно топливо поменять. Смысла не вижу Улыбающийся

не понял, о каком приёме на стороне прокси речь? транспорт используется внешний,  из qt забирается буфер, возвращается тоже буфер.
Есть какой то способ состыковать внешний транспорт и QWebView проще?
Записан
Bepec
Гость
« Ответ #7 : Июль 22, 2016, 15:06 »

Таки непонятно что вам надо. Запросы от QWebView это стандартные html'ные запросы, который любой прокси должен схавать без дополнительных причуд.

Записан
Krizis
Гость
« Ответ #8 : Июль 22, 2016, 16:05 »

Таки непонятно что вам надо. Запросы от QWebView это стандартные html'ные запросы, который любой прокси должен схавать без дополнительных причуд.



Мне надо именно сторонним транспортом передавать эти запросы.
Сейчас в основном это уже работает, повидимому, вебкит действительно не ожидает сигналов из того же потока, в котором создаётся запрос.  Что то похожее вы сразу и писали.
В приближенной к боевой, реализации - уже воспринимает:


Код:
#include <QNetworkReply>
#include <qcoreapplication.h>
#include <QtCore/QMetaObject>

class ProxyNetworkReply: public QNetworkReply
{
    Q_OBJECT

public:
    ProxyNetworkReply(QObject *parent, const QNetworkRequest &req,
            const QNetworkAccessManager::Operation op)
        : QNetworkReply(parent)
    {
        setRequest(req);
        setUrl(req.url());
        setOperation(op);


    }
    void abort() { QNetworkReply::close(); }
    qint64 bytesAvailable() const { return m_content.size() - m_lOffset; }
    bool isSequential() const { return true; }

    qint64 size() const
    {
        return  m_content.size();
    }


    void setData(QString string)
    {
        setFinished(true);

        QNetworkReply::open(QIODevice::ReadOnly | QIODevice::Unbuffered);

        //QString string = "<!DOCTYPE HTML><html> <head>  </head> <body><H1> description</H1></body></html>";

        m_content = string.toUtf8();
        m_lOffset = 0;

        setHeader(QNetworkRequest::ContentTypeHeader,
                QVariant("text/html; charset=UTF-8"));
        setHeader(QNetworkRequest::ContentLengthHeader,
                QVariant(m_content.size()));

        QMetaObject::invokeMethod(this, "metaDataChanged",
                Qt::QueuedConnection);
        QMetaObject::invokeMethod(this, "downloadProgress",
                Qt::QueuedConnection, Q_ARG(qint64, m_content.size()), Q_ARG(qint64, m_content.size()));
        QMetaObject::invokeMethod(this, "readyRead",
                Qt::QueuedConnection);

        QMetaObject::invokeMethod(this, "readChannelFinished",
                Qt::QueuedConnection);

        QMetaObject::invokeMethod(this, "finished",
                Qt::QueuedConnection);

            QCoreApplication::postEvent(this, new QEvent(QEvent::NetworkReplyUpdated));
    }

    protected:

    qint64 readData(char* pData, qint64 lMaxSize)
    {
        if (m_lOffset >= m_content.size())
            return -1;

        qint64 lCount = qMin(lMaxSize, m_content.size() - m_lOffset);
        memcpy(pData, m_content.constData() + m_lOffset, lCount);
        m_lOffset += lCount;
        return lCount;
    }

private slots:

private:
    QByteArray m_content;
    qint64 m_lOffset;
};

Записан
Bepec
Гость
« Ответ #9 : Июль 22, 2016, 16:12 »

Как я уже говорил - он не успевал подцепить connect к сигналам. И поэтому всё что вы в конструкторе писали летело куда угодно, но не webView.
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.058 секунд. Запросов: 22.