Simple WebKit2 example with Qt - c++

I'm trying to build a super simple dummy web-view with Qt and WebKit to view pages, so that I can better understand the WebKit2 split process model.
Existing examples/questions (like Example code for a simple web page browser using WebKit QT in C++) seem to use the "old" style WebKit, in which rendering and displaying are done in one process. What is the equivalent of that example but done for WebKit2?
Is it so difficult with WebKit2 that there aren't any basic examples out there?

Qt's WebKit2 is available only for QML.
With Qt 5 and Webkit2 the APIs for QtWebKit and Web View are changing significantly. This is because with WebKit2, WebKit and the application run in different processes. The old QWebView widget will only be supported on Qt for desktops and won't use the new WebKit2. Mobile phone platforms typically won't have the QWidgets module installed in Qt 5.
Examples which uses QtWebKit QML API that utilizes the WebKit2 split-process architecture could be found in Qt WebKit documentation There is Flickr View and YouTube View examples
Qt also has WebView module with examples like Minibrowser
And WebEngine module. Examples can be found here
And here is a simplest WebKit2 example which just shows google webpage
Use Qt 5.5.1 to run this example.
Add following to your .pro file: QT += quick qml webkit
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())return -1;
return app.exec();
}
main.qml
import QtQuick 2.0
import QtQuick.Window 2.0
import QtWebKit 3.0
Window {
visible: true
width: 967
height: 480
WebView {
id: webView
anchors.fill: parent
opacity: 0
url: "https://google.com"
Behavior on opacity
{
NumberAnimation { duration: 200 }
}
onLoadingChanged:
{
switch (loadRequest.status)
{
case WebView.LoadSucceededStatus:
opacity = 1
break
default:
opacity = 0
break
}
}
onNavigationRequested:
{
request.action = WebView.AcceptRequest
}
}
}

Related

Mapbox is not loading on raspberry

I'm trying to load a mapbox in my c++/qt application. On my PC the application is working fine, and the map is loaded. However, when the
application is deployed on the raspberry(v3) the application is running but the map is not loaded(a blank screen appears).
I've tried a different map plugins such as esri and they work fine
on the raspberry. But the mapbox plugin wont work
Here is the code I'm working on
import QtQuick 2.0
import QtQuick.Window 2.0
import QtLocation 5.6
import QtPositioning 5.6
Window {
width: 512
height: 512
visible: true
Plugin {
id: mapPlugin
name: "mapboxgl" // "mapboxgl", "esri", ...
// specify plugin parameters if necessary
// PluginParameter {
// name:
// value:
// }
}
Map {
anchors.fill: parent
plugin: mapPlugin
center: QtPositioning.coordinate(41.38, 2.16) // Oslo
zoomLevel: 14
}
}
And the C++ code
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
I'm expecting a mapbox type map to be loaded but only a blank screen appears. There are no any error messages.
I think it's because a plugin is missing or something. But then why it is working on my laptop since I have the same version of QT in both machines: (QT 5.10)

how can I put a splashscreen on my project using EGFLS in qt

I am developing a user interface with qt/QML and I need to show a splashscreen image at the begininning of the application.
I'm running the application on a device with a iMX6 microprocessor.
I used the library QtSplashscreen but it gives me this error: EGLFS: openGL windows cannot be mixed with others.
I know that it cannot open 2 windows simultaneously, can somebody help?
About your problem, see this question:
OpenGL and Qt Quick 2 applications can only have one fullscreen window existing at a time. Trying to create another OpenGL window, or trying to mix an OpenGL window with a raster one will display the above message and abort the application.
QSplashScreen use another window to show the splash view. So, this is not a direct solution. You can embed your QWidget inside a QQuickItem to use it as QtQuick2 control components.
Another, and faster solution is to use a QML component and load it with a Loader. You can take a look in the Qt Examples Repository, this file is a good example.
Here we go with an easy example;
Loader {
id: splashLoader
anchors.fill: parent
source: "SplashScreen.qml"
asynchronous: false
visible: true
onStatusChanged: {
if (status === Loader.Ready) {
appLoader.setSource("App.qml");
}
}
}
Connections {
target: splashLoader.item
onReadyToGo: {
appLoader.visible = true
appLoader.item.init()
splashLoader.visible = false
splashLoader.setSource("")
appLoader.item.forceActiveFocus();
}
}
Loader {
id: appLoader
anchors.fill: parent
visible: false
asynchronous: true
onStatusChanged: {
if (status === Loader.Ready)
splashLoader.item.appReady()
if (status === Loader.Error)
splashLoader.item.errorInLoadingApp();
}
}

Use QQuickView or QQmlApplicationEngine to switch between pages from ApplicationWindow

I'd like to use an ApplicationWindow as a main file and be able to switch to other QML files from C++ with QQuickView::setSource(const QUrl & url). Basically it would do this:
start-up => loads main.qml (ApplicationWindow) => click on help button => C++ loads help.qml file => etc.
int main(int argc, char *argv[])
{
QApplication app{argc, argv};
CustomQQuickView view;
view.setSource(QUrl{"qrc:/main.qml"});
view->show();
return app.exec();
}
main.qml
ApplicationWindow
{
visible: true
width: 640
height: 480
Loader
{
anchors.fill: parent
id: mainPageLoader
}
Button
{
text: "Help"
onClicked: { mainPageLoader.source = "help.qml"}
}
}
(I am wondering if the Loader here is really necessary here)
However QQuickView only supports loading of root objects that derive from QQuickItem. Therefore it doesn't work with ApplicationWindow.
I'm thinking about using QQmlApplicationEngine instead of QQuickView but the usage seems different, this class being only equipped with QQmlApplicationEngine::load(const QUrl & url)
What would be the best course of action for my purpose? Do I really need an ApplicationWindow in my main.qml file?
Use QQmlApplicationEngine as you suggest, and with the main.qml as you say, but set a context property from C++ with the content page URL, e.g. help.qml - then bind to this context property in the Loader's source property.
This is the normal way of controlling QML from C++ - expose context properties or singleton objects with properties, drive them from C++, and have QML bindings respond to changes.

Extending QML ApplicationWindow in C++

How can you properly extend the QML ApplicationWindow type? According to the documentation, ApplicationWindow instantiates a QQuickWindow. So I tried sub classing from QQuickWindow and exposing the type to QML as MyWindow. The problem is that MyWindow doesn't actually extend the QML type ApplicationWindow, so you don't get all the properties like menuBar and toolBar. How can I extend ApplicationWindow in C++ and expose it to QML? Here is what I'm currently doing:
class MyQuickWindow : public QQuickWindow
{
//...irrelevant additions
}
int main()
{
QGuiApplication app(argc, argv);
qmlRegisterType<MyQuickWindow>("MyExtensions", 1, 0, "MyApplicationWindow");
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:///main.qml")));
return app.exec();
}
Here is the QML file:
import QtQuick 2.0
import QtQuick.Controls 1.2
import QtQuick.Layouts 1.1
import MyExtensions 1.0
MyApplicationWindow {
width: 800
height: 600
visible: true
menuBar: MenuBar { // ERROR: menuBar is not a property
Menu {
title: "File"
MenuItem { text: "New" }
MenuItem { text: "Open" }
}
}
}
Note that I need to have my own additions in C++ to the QQuickWindow for other reasons.
It seems like the job for qmlRegisterType. And it is a bit hard to say if you miss something with your C++ part but registering the type should help. That is for exposing the type itself and should enable the derived QQuickWindow functionality (derived from ApplicationWindow actually). But for what you are adding you need to deal with Q_PROPERTY and Q_INVOKABLE (which is for functions) mechanism. See the whole bunch of Q_* QObject macro.
And if that was not enough then there is an example for such inheritance.
Correction: the author is dealing with QML-made type but he can still try to mimic the type on his own. The path to ApplicationWindow.qml source code is: C:\Qt\5.3\Src\qtquickcontrols\src\controls where C:\Qt\5.3\ is the root for selected Qt version.I would attempt that and that is feasible unless we want to find out about explicit QML inheritance. That file can also be found at Qt source code repository.

QML translation

I try to use translation in QML. I opened a new project QtQuick project, I chose QtQuick Componenets for Symbian as a QtQuick Application Type. Qt Creator created a application source tree with all standard files (main.cpp, main.qml, mainpage.qml...)
MainPage.qml is very simple:
import QtQuick 1.1
import com.nokia.symbian 1.1
Page {
id: mainPage
Text {
anchors.centerIn: parent
text: qsTr('Hello world!')
color: platformStyle.colorNormalLight
font.pixelSize: 20
}
}
My main.cpp file looks after implementation of QTranslator like this:
#include "qmlapplicationviewer.h"
#include <QTranslator>
#include <QPushButton>
#include <QDebug>
Q_DECL_EXPORT int main(int argc, char *argv[])
{
QScopedPointer<QApplication> app(createApplication(argc, argv));
QTranslator* translator = new QTranslator;
qDebug()<<"Translating: "<<translator->load(QString("qml/International/inter_en"));
app->installTranslator(translator);
//QPushButton hello(QPushButton::tr("Hello world!"));
// hello.resize(100, 30);
// hello.show();
QScopedPointer<QmlApplicationViewer> viewer(QmlApplicationViewer::create());
viewer->setMainQmlFile(QLatin1String("qml/International/main.qml"));
viewer->showExpanded();
return app->exec();
}
Then I run lupdate mainpage.qml -ts inter_en.ts , I have used linguist to translate the POSIX expression "Hello world!" to something else just test that it is translating. Then I created inter_en.qm file with linguist.
But when I run the application on simulator I dont get "Hello world!" translated, although the translator is loaded successfully (I get "Translating: true" in qDebug).
Translator is working correctly I am sure, because when I deremark part of the code with QPushButton , (again I repeat the lupdate and linguist things for this purpose) , then the "Hello world!" expression in QPushButton is translated correctly.
It is only the QmlApplicationViewer and QML file that is not performing translation correctly.
Any quesses?????
Thanks
UPDATE
I found out the following: MainPage.qml is imported as reusable component into main.qml. If I use qsTr() in main.qml then the text is translated correctly in main.qml. However text in MainPage.qml is not tranlated correcty. I guess due to importing it as reusable component. Any comments? Experiences?
UPDATE2 - SOLUTION
Translation files need to be created case sensitively:
lupdate mainpage.qml -ts myapp_sk.ts is wrong
lupdate MainPage.qml -ts myapp_sk.ts is correct
When the issue is not the translation per se, but changing language during runtime this may help you.
If you load a new QTranslator with app->installTranslator(translator);
it (QApplication) will fire a change event. In your Qt class you have to catch it with
/*!
on the fly translation
*/
void MyQmlView::changeEvent(QEvent *event)
{
if (event->type() == QEvent::LanguageChange)
{
// triggers qml function/slots
emit retranslate();
}
else
{
QWidget::changeEvent(event);
}
}
Somewher after loading your "main.qml":
m_pQmlView->rootContext()->setContextProperty( "_view", this );
QML side:
Component.onCompleted: {
/********************** Connections ***************************/
// connect Qt signal MyView::retranslate() with QML function (slot) retranslate
_view.retranslate.connect(retranslate)
}
// slot!
function retranslate () {
lblHelloWord.text = qsTr("Hello Word")
}
This works very good for MS Windows Platform.
I also use QML files as reusable components and I have no problem with translations at all. So I guess the following can help you as well.
I also guess you don't want to call lupdate manually for every file. So you should use the following lines in .pro file to make it look for all translatable phrases in QML and JS files automatically (correct your paths)...
lupdate_hack{
SOURCES += qml/*.qml \
qml/*.js
}
TRANSLATIONS = \
langs/WakeOnLAN_cs.ts \
langs/WakeOnLAN_pl.ts \
langs/WakeOnLAN_es.ts \
langs/WakeOnLAN_fr.ts \
langs/WakeOnLAN_it.ts \
langs/WakeOnLAN_hu.ts \
langs/WakeOnLAN_fa.ts \
langs/WakeOnLAN_de.ts \
langs/WakeOnLAN_pt.ts
CODECFORTR = UTF-8
It doesn't come from my head, so here is the source (there is also a note about dynamic translation): https://forum.qt.io/topic/30076/is-there-a-way-to-use-linguist-in-global-context