How to change WebView settings from QML - qt

I'm using a simple WebView in my QML file.
WebView {
anchors.fill: parent
url: "file:///android_asset/example.html"
}
The problem is, that I'm getting an error about access-control-allow-origin is null. I found a fix for this here, which is using WebView settings property. It seems to be accessible from c++, but I haven't found any way of using this property from qml. So how can I use WebView settings from QML to get rid of the error? I'm using Qt 5.10.

Use Qt's resource system, add the file to it, and load the file via
url: "qrc:///android_assets/example.html"

Related

Using QML FileDialog leads to "Binding loop" in ToolBar

I have an issue that I can't solve by myself. I develop a UI using this third party library/framework - https://github.com/papyros/qml-material. It is with controls and layouts developed according to the Google Guidelines. The problem is that when I use FileDialog in the project, the page that it is defined in loads slowly and I get the following messages:
file:///C:/.../QtQuick/Controls/ToolBar.qml:146:9: QML QQuickItem*: Binding loop detected for property "layoutHeight"
file:///C:/.../QtQuick/Dialogs/DefaultFileDialog.qml:407:9: QML ToolBar: Binding loop detected for property "implicitHeight"
file:///C:/.../QtQuick/Dialogs/DefaultFileDialog.qml:407:9: QML ToolBar: Binding loop detected for property "implicitHeight"
It will be great if someone knows the answer.
The issue can be reproduced very easily with the Demo that is in the GitHub project of the library - https://github.com/papyros/qml-material/tree/develop/demo. Just add FileDialog somewhere there and see how the page will be loaded and what messages you will get.
Qt version used: 5.12.6
This is a somewhat known problem with FileDialogs when put in Loaders that are set to asynchronous loading. Here is a complete example demonstrating the problem:
import QtQuick.Window 2.12
import QtQuick.Dialogs 1.3
Window {
id: root
visible: true
width: 640
height: 480
Loader {
sourceComponent: FileDialog {}
asynchronous: true // change to false and ToolBar binding loop goes away
}
}
I noticed that the project you have referenced uses an asynchronous Loader in main.qml, so it appears that this is causing your issue. See line 243:
Loader {
id: example
anchors.fill: parent
asynchronous: true
I have found one bug report but it has been closed as unresolved. My understanding of this problem is that the error only affects the "backup" QFileDialog that only appears if an OS-specific one is not available. From the documentation:
The implementation of FileDialog will be a platform file dialog if possible. If that isn't possible, then it will try to instantiate a QFileDialog.
In my experience, on Windows and Mac, the binding loop error causes no problems and can be ignored because the OS file dialog always appears. I also don't think it is a correctable error outside of not using the asynchronous flag, as it is a Qt bug.

QtWebEngine doesn't support JavascriptCanCloseWindows

In QtWebkit, using QWebSettings class, I could enable like the permission to close the window using the JavaScript command window.close();:
setAttribute(QWebSettings::JavascriptCanCloseWindows, true);
But in QtWebEngine, such an attribute doesn't exist: http://doc.qt.io/qt-5/qwebenginesettings.html#WebAttribute-enum
How to allow JavaScript to close any QWebEngineView using window.close()?
Indeed, this attribute doesn't exist anymore in the Qt WebEngine.
However, you can close any views using the signal windowCloseRequested from your QWebEnginePage, and connecting it to a slot where you close the window. There is an example of use in the Demo Browser example, in the file webview.cpp:
connect(page(), &WebPage::windowCloseRequested, this, &QWidget::close);

Zoom feature for QWebEngine does not work

I created simple project for displaying local .html page.
I used Qt5.4 with QWebView there. But after switching to Qt5.6 I noticed
that Qt WebKit is deprecated and not supported any more.
Thus I decided to replace Qt WebKit functionality with one from the
Qt WebEngine.
After replacing QWebView with QWebEngineView
I investigated that setZoomFactor method has no effect.
Is it known issue? How can I handle with this?
EDIT:
An interesting thing have been investigated recently. I use setHtml method for setting content of local .html files to my QWebEngineView. These files also contain references to images. So I set baseUrl parameter as a relative path to required images. In that case using of setZoomFactor method has no effect.
But when I don't set relative path to images as parameter, images are absent on QWebEngineView but zoom functionality works. Any ideas what is wrong here?
Setting zoomFactor for QML WebEngineView in Qt 5.11 using QML zoomFactor property or C++ setZoomFactor (private-API) did not work as expected. I discovered from comments in QT Bug 51992 that it works when set after a page load.
QML solution:
WebEngineView {
// ...
onLoadingChanged: {
zoomFactor = 0.75
}
}
QWebEngineView solution: connect to the loadFinished signal, and set zoomFactor after each page load:
main.cpp (after engine.load call):
QWebEngineView *webView; // = ...
QObject::connect(webView, &QWebEngineView::loadFinished,
[=](bool arg) {
webView->setZoomFactor(zoomFactor);
});
It seems to be a known bug in this version of Qt. You can check by yourself here : Qt Bug 51992.
Basically, it is said that :
This looks like a known glitch that is currently happening because of
the Chromium API that we use for setting the zoom factor.
And also :
Chromium limits the zoom factor to a maximum of 5.0 - any calls with a
number higher than that will have no effect.
Hope that will help you.
The setZoomFactor does not function properly in the QT 5.15 release.
Call setZoomFactor multiple times to resolve the problem.
WebEngineView {
function setZoomFactor(real) {
zoomFactor = real
zoomFactor = real
zoomFactor = real
}
}

How to display embedded html in Qt WebView

I am trying to get the Qt WebView to display an html file that is embedded as a Qt resource, but I can't seem to get it to work. I created a new Qt Quick application and added a simple qml file:
import QtQuick 2.0
import QtWebKit 3.0
Rectangle {
id: content
width: 800
height: 600
color: "black"
WebView {
id: webView
anchors.fill: parent
url: "qrc:/res/test.html"
}
}
I then created (using the Designer) a resource file that looks like this:
<RCC>
<qresource prefix="/res">
<file>test.html</file>
</qresource>
</RCC>
and created a simple test.html file (in the same directory as the .qrc file):
<html>
<head><title>Hello</title></head>
<body>
<h1>Hello World!</h1>
</body>
</html>
The result is just a blank white window. If I use a regular url (http://www.stackoverflow.com) in the qml file as the url it works - the page is displayed. If I use the name of an embedded image (qrc:/qt-project.org/mac/cursors/images/pluscursor.png) that image is displayed.
It looks to me as if the html file is indeed added (it is at least listed when I enumerate the embedded resources), but my understanding of the Qt resource system is limited, so I may very well have misunderstood something fundamental.
Can anyone tell me what I am doing wrong?
Update: I have verified that the behavior is the same if I attempt to tell the web view to load the url from C++ as well. I have also verified that the resource is indeed embedded - I can open and read the resource using a QResource. Also, this does not appear to be specific to Qt5: http://qt-project.org/forums/viewthread/18181 (someone having a similar problem with Qt 4.8).
First , make sure that resource file is compiled correctly on compile folder (a .RCC file or a qrc_<Resource name>.cpp)
Second, make sure your file path is correct (in my case qrc:/images/resource/html/test.html). You can open QRC file and right-click on html file and then click on Copy Resource Path to Clipboard.
Third, Note that some urls needs more time for loading completely.
Finally, I test this scenario and it works very well (Using Qt 5.1.0)
Good luck - S.M.Mousavi
I don't thing it's possible opening resource from qrc directly in WebView (I've tried all url variants). What I'm doing now is copying the file to the local temp directory and then opening.
QString helpHTMLFile = QStandardPaths::writableLocation(QStandardPaths::TempLocation);
helpHTMLFile.append(QDir::separator());
helpHTMLFile.append("software_manual.html");
QFile(helpHTMLFile).remove();
QFile(":/software_manual.html").copy(helpHTMLFile);
QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty("pathToFile", "file:///"+helpHTMLFile);
Then QML looks like:
WebView {
anchors.fill: parent
url: pathToFile
}
Ok, here's how I ended up solving this. I ended up using a plain widget instead of a qml based interface.
I then had to read the first html page out from the resources manually and provide the base url. After that, subsequent pages and resources that are embedded as resources load fine.
Here's the code in question:
QResource res(":/html/index.html");
ui->webView->setHtml(reinterpret_cast<const char *>(res.data()), QUrl("qrc:/html/"));
where webView is a QWebView. My .qrc file looks like this:
<RCC>
<qresource prefix="/">
<file>html/index.html</file>
</qresource>
</RCC>
This works in Qt 5.5.0.
The quickest way to load a resource file is using XMLHttpRequest and loadHtml().
This works in Qt 5.10.1 for mobile platforms.
import QtQuick 2.10
import QtQuick.Controls 2.3
import QtWebView 1.1
Page {
anchors.fill: parent
WebView {
id: webView
anchors.fill: parent
Component.onCompleted: {
var resource = 'qrc:/path/to/your/resource.html';
var xhr = new XMLHttpRequest;
xhr.open('GET', resource);
xhr.onreadystatechange = function() {
if (xhr.readyState === XMLHttpRequest.DONE) {
var response = xhr.responseText;
webView.loadHtml(response);
}
};
xhr.send();
}
}
}
why not just use
url: "res/test.html"
instead of
url: "qrc:/res/test.html"
?
Then you would not need to use any resource files
Embedded resources URLs loading support by web engine is available in latest Qt at least for WebEngineView in QML. I was not able to find official documentation about this, but one official sample loads page from resources:
WebEngineView {
url: "qrc:/index.html"
...
}
It works for me with Qt 5.8.0 as well.
You can put below line just after QApplication a(argc, argv);
QtWebView::initialize();
Just use Path-To-File & If you saved it in project directory, just set name of file
url: "/res/test.html"
& if file is in project directory
url: "test.html"

How to get the error message from a failed url load in a Qt WebView

say I have a basic QML file which listens for the onLoadFailed signal like this:
import QtQuick 1.1
import QtWebKit 1.0
WebView
{
onLoadFailed: {
}
url: "bogus_url"
}
In this example, I should get a 404 or a 500. What should I put in the onLoadFailed to output the error message that was returned?
I'm afraid you can't do it using a simple QML WebView.
You can use a [bad] trick described in this thread on the QT forum.
Otherwise you'll have to make your own QDeclarativeItem extending the WebView with all the infos you need.

Resources