Update QML Window property flags from C++ - qt

I have a basic qml application QWindow that already defines the property flags. I would like to change/update the property flags from main.cpp so that it is not frameless. I know I can do it directly in QML but I'd like to change it dynamically without re-compiling. I have found a number of examples but none show how to do this after using QQmlApplicationEngine::load() method. I posted my code below and I am able to see the current flags decimal value 2048 or hex value 0x800. According to documentation the hex value of 0x800 refers to Qt::FramelessWindowHint which is the current setting. I have tried to modify the flags property but the window doesn't update.
// Main.qml
import QtQuick 2.9
import QtQuick.Window 2.2
Window {
id: window
objectName: "window"
...
flags: Qt.FramelessWindowHint
...
}
// main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QWindow>
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.addImportPath("qrc:/");
QObject::connect(&engine, &QQmlApplicationEngine::quit, &app,
&QGuiApplication::quit);
const QUrl url(QStringLiteral("qrc:/Main.qml"));
QObject::connect(
&engine, &QQmlApplicationEngine::objectCreated, &app,
[url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl) QCoreApplication::exit(-1);
QVariant obj2 = obj->property("flags");
if (obj2.isValid()) {
Qt::WindowFlags flags = qvariant_cast<Qt::WindowFlags>(obj2);
flags &= ~Qt::FramelessWindowHint;
auto *tmp = dynamic_cast<QWindow*>(obj);
tmp->setFlags(flags);
tmp->show();
}
},
Qt::QueuedConnection);
engine.load(url);
return app.exec();
}

you have obj and if you want that main.qml change you can easily add property to this:
obj->setProperty("flags", Qt::FramelessWindowHint);
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QWindow>
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl)
{
if (!obj && (url == objUrl))
{
QCoreApplication::exit(-1);
}
obj->setProperty("flags", Qt::FramelessWindowHint);
}, Qt::QueuedConnection);
engine.load(url);
return app.exec();
}
Edited :

Related

I want to know the line number in editText where the cursor is

I want to know the line number in editText where the cursor is. How do I get that?
I checked the documentation, and there's no
ps:Is the textedit QML,not QTextEdit
You have to use textDocument and cursorPosition properties in c++:
main.cpp
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QQuickTextDocument>
#include <QTextBlock>
class Helper: public QObject{
Q_OBJECT
public:
Q_INVOKABLE int currentLineNumber(QQuickTextDocument *textDocument, int cursorPosition){
if(QTextDocument * td = textDocument->textDocument()){
QTextBlock tb = td->findBlock(cursorPosition);
return tb.blockNumber();
}
return -1;
}
};
#include "main.moc"
int main(int argc, char *argv[])
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
Helper helper;
engine.rootContext()->setContextProperty("helper", &helper);
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.load(url);
return app.exec();
}
main.qml
import QtQuick 2.15
import QtQuick.Window 2.15
Window {
width: 640
height: 480
visible: true
TextEdit{
id: textEdit
anchors.fill: parent
onCursorPositionChanged: function(){
let line = helper.currentLineNumber(textEdit.textDocument, textEdit.cursorPosition);
console.log(line);
}
}
}

How can I record a window using ffmpeg by id?

I want to get the id of the window by name using c++ or qml and record the specific screen using this id in ffmpeg.
ffmpeg -f x11grab -wid 0x6200012 -s 1920x1052 -r 30 -i :0.0+0,0
How can I do this?
it's not necessary to be the id, can be the offset-x and offset-y, I just want to record the window in any position.
I do not see that x11grab can record some screen by id as this answer indicates so as that answer points out one option is to use GStreamer:
gst-launch-1.0 ximagesrc xid=0x04000007 ! videoconvert ! autovideosink
How do I get the window id in Qt?
If QQmlApplicationEngine is used with Window or ApplicationWindow:
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QWindow>
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url, &engine](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
if(QWindow *w = qobject_cast<QWindow *>(engine.rootObjects().first())){
qDebug() << w->winId();
}
}, Qt::QueuedConnection);
engine.load(url);
return app.exec();
}
With QQuickView
#include <QGuiApplication>
#include <QQuickView>
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQuickView view;
const QUrl url(QStringLiteral("qrc:/main.qml"));
view.setSource(url);
view.show();
qDebug() << view.winId();
return app.exec();
}
Qt Widgets:
#include "mainwindow.h"
#include <QApplication>
#include <QDebug>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
qDebug() << w.winId();
return a.exec();
}
Or in general you should access the QWindow and get the window id:
for(QWindow *w : QGuiApplication::allWindows()){
qDebug() << w->winId();
}
I found out the following:
ffmpeg -y -s 800x600 -f x11grab -window_id 0x3200008 -framerate 30 -i :11.0+0,0 -c:v libx264 -preset ultrafast -crf 40 output_select_window.mp4
Very important explanation:
-window_id = 'xwininfo' shows window_id if you select a window
-i :11.0+0,0 = 11 means and from in shell with `$echo $Display`.

qml parsing QVariant QJsonDocument to js object

A QVariant I took from C++ contains a QJsonDocument, and I want to convert it to a js object, but I only found the use of QJsonDocument in C++. I couldn't find how to use QJsonDocument in qml.
For Example:
Qml:
function qmlUpdateObject( Object ){
console.log(Object);
}
// console content: qml: QVariant(QJsonDocument, QJsonDocument({"appDesc":{"description":"SomeDescription","message":"SomeMessage"},"appName":{"description":"Home","imp":["awesome","best","good"],"message":"Welcome"}}))
// I want to get a js object: {"appDesc":{"description":"SomeDescription","message":"SomeMessage"},"appName":{"description":"Home","imp":["awesome","best","good"],"message":"Welcome"}}
C++:
QObject::connect( this, SIGNAL( updateData(QVariant)),
viewItem, SLOT( qmlUpdateObject(QVariant)) );
void Controller::setData(QString name)
{
QFile file("data.json");
QJsonDocument d = QJsonDocument::fromJson(file.readAll());
QByteArray dataJson = d.toJson(QJsonDocument::Compact);
emit updateData(dataJson);
}
UPDATE
Add this line and pass back, qml can successfully parse:
QByteArray dataJson = d.toJson(QJsonDocument::Compact);
There is no direct QJsonDocument conversion to a js object. One possible solution is to convert the QJsonDocument to QByteArray and export it to QML, and in QML do parse using JSON.parse():
C++
QByteArray dataJson = doc.toJson(QJsonDocument::Compact);
// send dataJson to QML
QML
var json = JSON.parse(dataJson)
Note:
It seems that the OP does not know the good practice of not accessing QML objects from C++ but must create a QObject and export it to QML.
The example provided by the OP is not necessary to use QJsonDocument since JSON.parse() does the same as QJsonDocument d = QJsonDocument::fromJson(file.readAll());.
#include <QFile>
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
class Controller: public QObject{
Q_OBJECT
public:
void setData(const QString & filename){
QFile file(filename);
if(file.open(QIODevice::ReadOnly))
Q_EMIT updateData(file.readAll());
}
Q_SIGNALS:
void updateData(const QByteArray & data);
};
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
Controller controller;
QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty("controller", &controller);
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.load(url);
controller.setData("data.json");
return app.exec();
}
#include "main.moc"
import QtQuick 2.14
import QtQuick.Window 2.14
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
function qmlUpdateObject( data ){
var obj = JSON.parse(data)
console.log(obj);
}
Connections{
target: controller
onUpdateData: qmlUpdateObject(data)
}
}

QML: QT Project does not run after modifying the code

I'm learning the QT basic, starting the new project QT Quick APP Empty. Running for first time, the app run. Modifying the code:
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.VirtualKeyboard 2.4
Window { x: 100; y: 100; width: 100; height: 100; visible: true }
Output response:
17:34:02: Starting /home/PC/Documents/Projects/QT_APP/build-FirstAPP-Desktop_Qt_5_12_2_GCC_64bit-Release/FirstAPP ...
Nothing besides that happens. Am I forgetting anything?
Updating
#include <QGuiApplication>
#include <QQmlApplicationEngine>
int main(int argc, char *argv[])
{
qputenv("QT_IM_MODULE", QByteArray("qtvirtualkeyboard"));
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.load(url);
return app.exec();
}
Worked, after I Clean and build project again!

Import Qt function to QML file?

How do you call for example QFile::exists(path) inside a QML file in Qt 5.5?
MyFile.qml
import QtQuick 2.5
// These are some various things I've tried, with the error message they
// give related to the row where I call QFile::exists()
#include <QFile> // Expected token `{'
import QtQml 2.5 // Expected token `;'
import io.qt // Expected token `;'
import io.qt.QFile // Expected token `;'
Item {
id: root
property string imageSource
Image {
id: test
source: fileOrFallback(root.imageSource)
}
function fileOrFallback (source) {
return QFile::exists(source)
? preprocessor.getFilePath(source)
: theme.example + 'placeholder.png'
}
}
I've seen some examples on how to import your custom Qt functions, but how do you call built-in Qt functions in QML?
You cannot directly import a C ++ function, in these cases the approach is to create a QObject that exposes the method through a Q_INVOKABLE:
backend.h
#ifndef BACKEND_H
#define BACKEND_H
#include <QObject>
class Backend : public QObject
{
Q_OBJECT
public:
using QObject::QObject;
Q_INVOKABLE bool exists(const QString &fileName);
};
#endif // BACKEND_H
backend.cpp
#include "backend.h"
#include <QFile>
bool Backend::exists(const QString &fileName){
return QFile::exists(fileName);
}
main.cpp
#include "backend.h"
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
Backend backend;
QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty("backend", &backend);
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.load(url);
return app.exec();
}
*.qml
// ...
function fileOrFallback (source) {
return backend.exists(source)
? preprocessor.getFilePath(source)
: theme.example + 'placeholder.png'
}
// ...

Resources