I would like to display an error page in a QWebView
. For example if the server returns a 404 Error the QWebView
should display a its own custom 404 Error instead of the one sent from the server.
I use the QWebPage::extension
to handle error conditions and it works well for Network Errors.
However if the server returns an error 404 and at the same time returns an error page, this page is displayed and the QWebPage::extension
method is never called.
Is there a way to force QtWebKit to invoke the error handler and override the server error page?
After hopping around the code long enough, trying various things, the following seems to solve at least my case:
MyWebPageSubclass::MyWebPageSubclass(...) {
connect(networkAccessManager(), SIGNAL(finished(QNetworkReply*)), this, SLOT(handleNetworkFinished(QNetworkReply*)));
// ...
}
void MyWebPageSubclass::handleNetworkFinished(QNetworkReply *reply) {
bool ok = false;
int httpStatus = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(&ok);
if (ok && httpStatus / 100 != 1 && httpStatus / 100 != 2 && httpStatus / 100 != 3) {
if (!supportsExtension(ErrorPageExtension)) {
return;
}
ErrorPageExtensionOption option;
option.domain = Http;
option.error = httpStatus;
option.url = reply->url();
option.errorString = reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString();
ErrorPageExtensionReturn output;
if (!extension(ErrorPageExtension, &option, &output)) {
return;
}
mainFrame()->setContent(output.content, output.contentType, output.baseUrl);
}
}
One note, if you replace mainFrame content in handleNetworkFinished() slot you may see your error page instead of loaded page if network errors occurred with the page elements (like external images or scripts).
Another option would be re-implementing QWebPage::extension() and QWebPage::supportsExtension(), in which case QT Webkit will call your implementation of extension() for page errors and replace page content with the page you provided, like:
class WebPage : public QWebPage
{
Q_OBJECT
public:
WebPage(QObject *parent = 0);
bool extension(Extension extension,
const ExtensionOption *option,
ExtensionReturn * output);
bool supportsExtension(Extension extension) const;
};
bool WebPage::extension(Extension extension,
const ExtensionOption *option,
ExtensionReturn * output)
{
if(!option || !output) {
return false;
}
if(extension == QWebPage::ErrorPageExtension) {
const ErrorPageExtensionOption *errOption =
static_cast<const ErrorPageExtensionOption*>(option);
QString errPage;
errPage = "<html><body><h1>";
errPage += "Page loading error, URL: ";
errPage += errOption->url.toString();
errPage += "</h1><h3>Error occurred in the ";
switch (errOption->domain) {
case QWebPage::QtNetwork:
errPage += "QT network layer, code is: ";
break;
case QWebPage::Http:
errPage += "HTTP layer, HTTP error code is: ";
break;
case QWebPage::WebKit:
errPage += "WebKit internals, error code is: ";
break;
default:
errPage += "Unknown domain, error code is: ";
}
errPage += errOption->error;
errPage += "</h3><h4><br>Error text: ";
errPage += errOption->errorString;
errPage += "</h4></body></html>";
ErrorPageExtensionReturn *errReturn =
static_cast<ErrorPageExtensionReturn*>(output);
errReturn->baseUrl = errOption->url;
errReturn->content = errPage.toUtf8();
// errReturn->contentType = "text/html"
// errReturn->encoding = "UTF-8"; // these values are defaults
return true;
}
return false;
}
bool WebPage::supportsExtension(Extension extension) const
{
if(extension == QWebPage::ErrorPageExtension) {
return true;
}
return QWebPage::supportsExtension(extension);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With