How to choose the OpenGL context for QtQuick applications - c++

I am writing an QtQuick application, mainly in QML, but I have some parts that use OpenGL more directly (an OpenSceneGraph scene). For some reasons, I want to use OpenGL version >= 3.3, but Qt only choose a 3.0 implementation. My code is:
main.cpp:
#include <QApplication>
#include <QQmlApplicationEngine>
int main(int argc, char *argv[])
{
// Create the app.
QApplication app(argc, argv);
// Start the UI.
QQmlApplicationEngine engine;
engine.load(QUrl("main.qml"));
return app.exec();
}
main.qml:
import QtQuick 2.7
import QtQuick.Controls 2.2
ApplicationWindow {
id: root
width: 800
height: 600
title: "App"
visible: true
Label {
text: "OpenGL: " + OpenGLInfo.majorVersion + ' ' + OpenGLInfo.minorVersion + OpenGLInfo.profile
}
}

One way of doing it is to set the default QSurfaceFormat before the app.exec().
#include <QSurfaceFormat>
...
QSurfaceFormat surfaceFormat;
surfaceFormat.setMajorVersion(3);
surfaceFormat.setMinorVersion(3);
surfaceFormat.setProfile(QSurfaceFormat::CoreProfile);
QSurfaceFormat::setDefaultFormat(surfaceFormat);

Related

Qt WebEngine url blocking

I would like to ask you a question, how to correctly block some url access. I would like to block access to URLs like "file:///" on QtWebEngine. I was searching something about WebUrlRequestInterceptor and QWebEngineUrlSchemeHandler but, did I find the right answer?
// main.qml
import QtQuick 2.0
import QtQuick.Window 2.0
import QtWebEngine 1.1
Window {
id: window
width: 800
height: 600
WebEngineView {
id: webView
anchors.fill: parent
url: "file:///"
}
}
// request.cpp
#include <QtCore/QRegExp>
#include "request.h"
WebUrlRequestInterceptor::WebUrlRequestInterceptor(QObject *p)
:QWebEngineUrlRequestInterceptor(p)
{
}
void WebUrlRequestInterceptor::interceptRequest(QWebEngineUrlRequestInfo &info) {
if(!info.requestUrl().toString().contains(QRegExp("(?:https?|ftp)://\\S+")))
info.block(true);
}
// main.cpp
#include <QtGui/QGuiApplication>
#include <QtCore/QCoreApplication>
#include <QtQml/QQmlApplicationEngine>
#include <QtWebEngine/QQuickWebEngineProfile>
#include <QtWebEngine/QtWebEngine>
#include <QtQuick/QQuickWindow>
#include "request.h"
int main(int argc, char **argv) {
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
QGuiApplication app(argc, argv);
WebUrlRequestInterceptor *wuri = new WebUrlRequestInterceptor;
QQuickWebEngineProfile::defaultProfile()->setUrlRequestInterceptor(wuri);
QQmlApplicationEngine engine;
engine.load(QStringLiteral("./main.qml"));
QQuickWindow *window = qobject_cast<QQuickWindow*>(engine.rootObjects().first());
QRect rectangle;
rectangle.setWidth(800);
rectangle.setHeight(600);
window->setGeometry(rectangle);
window->show();
return app.exec();
}
Is it the right way, how I made it? I founded some flags here https://doc.qt.io/qt-5/qwebengineurlscheme.html#Flag-enum like QWebEngineUrlScheme::LocalAccessAllowed, but not sure, if this will help me. Isn't possible to control this list somehow https://admx.help/?Category=Chrome&Policy=Google.Policies.Chrome::URLBlocklist ?
Thank you

QQuickView as item in a QGraphicsScene

I would like to integrate a QQuickView in a QGraphicsView, but I only get a gray rectangle.
I know this is a horrible choice to integrate qml into qgraphicsview, but my team is working on this application for 3 years now and it is not possible to change the main QGraphicsView. I just want to know if there is a way to include some QML now.
Maybe there is a solution for this ? Maybe I just have to forget about it. Maybe you know. Thanks !
Code sample
main.cpp
#include <QApplication>
#include <QMainWindow>
#include <QtQuick/QQuickView>
#include <QGraphicsView>
#include <QGraphicsScene>
// Main
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QGraphicsScene * scene = new QGraphicsScene;
QGraphicsView * view = new QGraphicsView(scene);
QQuickView * quickView = new QQuickView;
quickView->setSource(QUrl::fromLocalFile("test.qml")); // Displays a text
QWidget * container = QWidget::createWindowContainer(quickView);
container->setFixedSize(500, 100);
scene->addWidget(container);
scene->addEllipse(50, 50, 100, 100); // Just to know my scene is correctly drawn
view->show();
return a.exec();
}
test.qml
import QtQuick 2.15
Rectangle {
width: 500
height: 100
Text {
text: "This is a text in a QML view"
anchors.left: parent.left
anchors.top: parent.top
}
}

Global functions or macros to get Qt version in QML code

How Can I get Qt version, for example 5.11.2 or similar, in my QML code. In my C++ code I have these options:
Method available on C++:
qVersion();
Macro available on C++:
QT_VERSION
But I couldn't find anything on QML?
You could use a Context Property, as explained here.
A simple example, given a simple qml file like this:
import QtQuick 2.9
import QtQuick.Window 2.2
Window {
Text {
text: qtversion
}
visible: true
width: 640
height: 480
title: qsTr("Hello World")
}
Set the qtversion property at startup, in main function:
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty("qtversion", QString(qVersion()));
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
return app.exec();
}

How to use GrabWindow?

I have found a class GrabWindow but I am a noobie in Qt Quick 2 and can't get how to use it.
Can a someone explain how can I use this view?
At this moment I added in my main function:
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QtQml>
#include "grabwindow.h"
int main(int argc, char *argv[]) {
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
qmlRegisterType<GrabWindow>("test", 1, 0, "GrabWindow");
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/qml/SystemTray.qml")));
if (engine.rootObjects().isEmpty()) {
return -1;
}
GrabWindow grabWnd;
grabWnd.setResizeMode(QQuickView::SizeViewToRootObject);
grabWnd.setSource(QUrl(QStringLiteral("qrc:/qml/main.qml")));
grabWnd.setFlags(Qt::Popup);
grabWnd.show();
return app.exec();
}
And my main.qml:
import QtQuick 2.9
import QtQuick.Controls 2.2
ApplicationWindow {
id: window
visible: true
width: 320
height: 480
title: qsTr("test")
}
But on start I get that only:
How to get a screenshot using that class and remove a square at the left top corner of the screen?
ADDED
I use Ubuntu 17.10

C++ type's destructor not called in QML

I create a Sailfish app (using latest Sailfish SDK). I have a problem with exposing a C++ object to QML. It inherits QSettings,
class Settings : public QSettings
{
Q_OBJECT
/**/
public:
explicit Settings() : QSettings("Marcin Mielniczuk", "BigText") {}
~Settings() { qDebug() << "Dying"; }
/**/
};
I noticed that the destructor isn't called at all. (there's not destructor output)
I create the object like that:
import QtQuick 2.0
import Sailfish.Silica 1.0
import BigText 1.0
import "pages"
ApplicationWindow
{
initialPage: MainPage { }
Settings {id: settings}
}
My main.cpp is:
Q_DECL_EXPORT int main(int argc, char *argv[])
{
QScopedPointer<QGuiApplication> app(Sailfish::createApplication(argc, argv));
qmlRegisterType<Settings>("BigText", 1, 0, "Settings");
QScopedPointer<QQuickView> view(Sailfish::createView("main.qml"));
Sailfish::showView(view.data());
return app->exec();
}
What am I doing wrong?
/edit: Text not being printed isn't an actual problem - it's just an indicator of the problem. The QSettings sycing in the destructor doesn't work too.
EDIT2: Please note, that ApplicationWindow in I'm using Sailfish Silica, not QtQuick.Controls, and the window is shown ok. These components must be a somewhat different to the stock qt quick components.
There's nothing inherently wrong with your logic. Here is a simplified version of it. I can run it locally, and consistently get a Dying message on output every time the window is closed and the application terminates.
If you cannot figure it out, I suggest transforming this code into what you're doing until it fails.
By the way, this is surely just a snippet of something larger you're doing, but at least as far as the example goes, these scoped pointers aren't doing much.
main.qml
import QtQuick 2.0
import BigText 1.0
Item {
width: 300; height: 300
Settings {id: settings}
}
main.cpp
class Settings : public QSettings
{
Q_OBJECT
public:
Settings() : QSettings("Marcin Mielniczuk", "BigText") {}
~Settings() { qDebug() << "Dying"; }
};
int main(int argc, char *argv[])
{
QScopedPointer<QGuiApplication> app(new QGuiApplication(argc, argv));
qmlRegisterType<Settings>("BigText", 1, 0, "Settings");
QScopedPointer<QQuickView> view(new QQuickView());
view->setSource(QUrl::fromLocalFile("main.qml"));
view->show();
return app->exec();
}
You could try to put and id yo tour ApplicationWindow and explicity use the destroy() method at some time and see what happens.
You cannot use QQuickView with an ApplicationWindow class. Not only is your destructor not called, your constructor isn't either, because the loading doesn't ever succeed.
The code below works fine under Qt 5.1.1. Tested on both OS X 10.8 and Windows 7.
main.qrc
<RCC>
<qresource prefix="/">
<file>main.qml</file>
</qresource>
</RCC>
main.pro
QT += core gui qml quick
TARGET = qml-appwin-end-18597527
TEMPLATE = app
SOURCES += main.cpp
OTHER_FILES += main.qml
RESOURCES += main.qrc
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QSettings>
#include <QQuickWindow>
#include <QtQml>
#include <QDebug>
class Settings : public QSettings
{
Q_OBJECT
public:
Settings() : QSettings("Marcin Mielniczuk", "BigText") {}
~Settings() { qDebug() << "Dying"; }
};
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
qmlRegisterType<Settings>("BigText", 1, 0, "Settings");
engine.load(QUrl("qrc:/main.qml"));
QObject *topLevel = engine.rootObjects().value(0);
QQuickWindow *window = qobject_cast<QQuickWindow *>(topLevel);
window->show();
return app.exec();
}
#include "main.moc"
main.qml
import QtQuick 2.0
import QtQuick.Controls 1.0
import BigText 1.0
ApplicationWindow {
width: 300; height: 300
Settings {id: settings}
}
Nothing is wrong with my code. It's something with the SDK. Debugging shows
ASSERT: "QThread::currentThread() == QCoreApplication::instance()->thread()" in file debugger/qqmldebugserver.cpp, line 576
Then the program is aborted and therefore destructor not called.