Название: Собственный QNetworkReply :( не могу разобраться помогите....
Отправлено: knaklezz от Февраль 28, 2010, 18:14
Привет кьют начал изучать недавно, и попал в тупик :(
Собственно использую QWebKit для вывода сгенерированного программой html текста, весь контент для странички содержится в zip архивах поэтому использую ссылки вида: <img src="zip://pack_12.zip/1.jpg">, т.е мне надо реализовать обработчик для таких ссылок, я переопределил
QNetworkAccessManager.createRequest (Operation, QNetworkRequest, QIODevice device = None)
Создал свой
class MyNetworkReply : public QNetworkReply
переопределил в нем все виртуальные методы от QIODevice и QNetworkReply.
Устанавливаю Header Для картинки (image/jpeg), url (zip://pack_12.zip/1.jpg), QNetworkRequest.
Возвращаю экземпляр из функции QNetworkAccessManager.createRequest.
В итоге QWebKit не чего не загружает, единственную функцию которую вызывает QWebKit это QNetworkReply::url().
Кто нибуть переопределял класс QNetworkReply на свой, поделитесь опытом пожалуйста.
http://doc.trolltech.com/qq/32/qq32-webkit-protocols.html - читал, я понял что надо посылать readyRead() сигнал, но как узнать что QWebPage уже приконнектился к сигналу readyRead().
Название: Re: Собственный QNetworkReply :( не могу разобраться помогите....
Отправлено: SABROG от Февраль 28, 2010, 20:45
Думаю будет справедливо, если ты выложишь свои наработки, которые можно собрать и посмотреть чего ты забыл добавить или сделал не так. Вопрос не из разряда простых, тут телепаты нужны с третьим глазом, которые смогут на расстоянии в твои исходники посмотреть.
Название: Re: Собственный QNetworkReply :( не могу разобраться помогите....
Отправлено: knaklezz от Март 01, 2010, 00:45
Получилось :) использовал QThread посмотрите правильно ли реализовал, или еще есть более оптимальные варианты :) MyNetworkReply.h #pragma once
#include <QtNetwork/QNetworkReply> #include <QtCore/QFile> #include <QtCore/QByteArray>
#include <QtCore/QThread>
class MyNetworkReply : public QNetworkReply, QThread { private: QFile* m_file; QByteArray m_content; qint64 m_offset; public: MyNetworkReply(QObject* parent = 0); ~MyNetworkReply(); //QNetworkReply public: void abort(); void setConfig(const QUrl&, QNetworkAccessManager::Operation, const QNetworkRequest&); //QIODevice public: void run(); qint64 bytesAvailable() const; bool isSequential() const; bool open(OpenMode open); protected: qint64 readData(char* data, qint64 maxSize); };
MyNetworkReply.cpp #include "MyNetworkReply.h"
MyNetworkReply::MyNetworkReply(QObject* parent) : QNetworkReply(parent), QThread() { m_file = new QFile("1.jpg");
this->open(QIODevice::ReadOnly | QIODevice::Unbuffered);
m_offset = 0;
m_content = m_file->readAll();
this->setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/jpeg")); this->setHeader(QNetworkRequest::ContentLengthHeader, QVariant(m_content.size()));
this->start(); }
MyNetworkReply::~MyNetworkReply() { this->close();
delete m_file; }
void MyNetworkReply::abort() { this->close(); }
void MyNetworkReply::setConfig(const QUrl& turl, QNetworkAccessManager::Operation op, const QNetworkRequest& req) { this->setUrl(turl); this->setOperation(op); this->setRequest(req); }
qint64 MyNetworkReply::readData(char* data, qint64 maxSize) { if (m_offset < m_content.size()) { qint64 number = qMin(maxSize, m_content.size() - m_offset);
memcpy(data, m_content.constData() + m_offset, number);
m_offset += number;
return number; } else { return -1; } }
qint64 MyNetworkReply::bytesAvailable() const { return m_content.size() - m_offset; }
bool MyNetworkReply::isSequential() const { return true; }
bool MyNetworkReply::open(OpenMode open) { QIODevice::setOpenMode(open);
return m_file->open(open); }
void MyNetworkReply::run() { while(m_offset == 0) { emit QNetworkReply::readyRead(); emit QNetworkReply::finished(); } }
MyNetworkAccessManager.h #pragma once
#include <QtNetwork/QNetworkAccessManager>
class MyNetworkAccessManager : public QNetworkAccessManager { private: QNetworkReply* createRequest(Operation op, const QNetworkRequest& req, QIODevice* outgoingData = 0); public: MyNetworkAccessManager(); ~MyNetworkAccessManager(); };
MyNetworkAccessManager.cpp #include "MyNetworkAccessManager.h"
#include "MyNetworkReply.h"
MyNetworkAccessManager::MyNetworkAccessManager() : QNetworkAccessManager() { }
MyNetworkAccessManager::~MyNetworkAccessManager() { }
QNetworkReply* MyNetworkAccessManager::createRequest(Operation op, const QNetworkRequest& req, QIODevice* outgoingData) { MyNetworkReply* networkReply = new MyNetworkReply(this); networkReply->setConfig(req.url(), op, req);
return networkReply; }
main.cpp #include <windows.h>
#include <QtGui/QApplication> #include <QtWebKit/QWebView>
#include "MyNetworkAccessManager.h" #include "MyNetworkReply.h"
#pragma comment (lib, "QtGui4.lib") #pragma comment (lib, "QtCore4.lib") #pragma comment (lib, "qtmain.lib") #pragma comment (lib, "QtNetwork4.lib") #pragma comment (lib, "QtWebKit4.lib")
int main(int argc, char* argv[]) { QApplication app(argc, argv);
QWebView* webView = new QWebView();
webView->page()->setNetworkAccessManager(new MyNetworkAccessManager());
webView->page()->setForwardUnsupportedContent(true);
QWidget::connect(webView->page(), SIGNAL(unsupportedContent(QNetworkReply*)), &app, SLOT(aboutQt()));
webView->setHtml("<b>Image:</b><br><img border=\'1\' src=\'files/1.jpg\'>", QUrl("test://test.ru/"));
webView->show();
return app.exec(); }
Название: Re: Собственный QNetworkReply :( не могу разобраться помогите....
Отправлено: victor_yacovlev от Март 09, 2011, 22:32
Мне удалось сделать это без QThread: C++ (Qt) struct MiniServerResponse { QString mimeType; QByteArray data; int code; QString errorText; }; class MiniServerNetworkReply : public QNetworkReply { public: explicit MiniServerNetworkReply(const MiniServerResponse &response, QObject * parent = 0); ~MiniServerNetworkReply(); inline qint64 bytesAvailable() const { return data.size() - position; } inline bool isSequential() const { return true; } inline void abort() { } protected: qint64 readData(char *data, qint64 maxlen); qint64 position; private: QByteArray data; QString contentType; }; qint64 MiniServerNetworkReply::readData(char *buffer, qint64 maxlen) { qint64 cnt = qMin(maxlen, bytesAvailable()); const char * slice = data.mid(position, cnt).data(); qstrncpy(buffer, slice, cnt); return cnt; } MiniServerNetworkReply::MiniServerNetworkReply(const MiniServerResponse &response, QObject * parent) : QNetworkReply(parent) { QNetworkReply::open(QIODevice::ReadOnly); position = 0; contentType = response.mimeType; if (response.code==200) { // HTTP 200 is OK data = response.data; } else { QString error = QString("<html><head><title>Error %1</title></head><body><h1>Error %1</h1><p>%2</p></body></html>") .arg(response.code) .arg(response.errorText); data = error.toUtf8(); } setHeader(QNetworkRequest::LastModifiedHeader, QDateTime::currentDateTime()); setHeader(QNetworkRequest::ContentLengthHeader, data.size()); setHeader(QNetworkRequest::ContentTypeHeader, response.mimeType); QMetaObject::invokeMethod(this, "metaDataChanged", Qt::QueuedConnection); QMetaObject::invokeMethod(this, "downloadProgress", Qt::QueuedConnection, Q_ARG(qint64, data.size()), Q_ARG(qint64, data.size())); QMetaObject::invokeMethod(this, "readyRead", Qt::QueuedConnection); QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection); }
Название: Re: Собственный QNetworkReply :( не могу разобраться помогите....
Отправлено: BRE от Март 09, 2011, 22:40
Ну нельзя так делать: C++ (Qt) qint64 MiniServerNetworkReply::readData(char *buffer, qint64 maxlen) { ... const char * slice = data.mid(position, cnt).data(); // Здесь slice указывает на уже разрушенный буфер (то что это работает - случайность, может и не работать или работать не так. :) }
|