QT WebGL-stream, virtualKeyboard and touch screen problem - qt

As I see, the virtualKeyboard (plugin) sends touch and click event when qml application is running over WegGL-stream. Now I've trouble finding an easy workaround.. Does anyone have a good idea? Further is it a virtualKeyboard or a QPA-Plugin bug?
Tried with QT 5.13.0, MSVC2017 64Bit / MinGW 64Bit compiler, Windows10, Chrome 76.0.3809.132 64Bit / Firefox. If application is not running over WebGL-stream, everthing works fine in terms of touch and click events.
// Tests with QT Quick Virtual Keyboard example with extended main.cpp..
int main(int argc, char *argv[])
{
qputenv("QSG_RENDER_LOOP","threaded");
qputenv("QT_QPA_PLATFORM", "webgl:port=1051");
qputenv("QT_IM_MODULE", QByteArray("qtvirtualkeyboard"));
QGuiApplication app(argc, argv);
QQuickView view(QString("qrc:/%2").arg("basic-b2qt.qml"));
if (view.status() == QQuickView::Error)
return -1;
view.setResizeMode(QQuickView::SizeRootObjectToView);
view.show();
return app.exec();
}

Related

QProcess: Destroyed while process (Web Browser) is still running

Is it possible to close a window or tab in an external browser after starting it using a Qprocess?
I tried the following (for example):
#include <QCoreApplication>
#include "QProcess"
#include "QThread"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QProcess process;
process.start("C:/Program Files/Google/Chrome/Application/Chrome.exe", QStringList() << "google.com");
QThread::msleep(1000);
process.kill();
process.waitForFinished();
return a.exec();
}
But the process is not closed.
So, Is it not possible or there is a workaround? thanks.
Well this is not the best solution but I here it is:
QProcess::execute("taskkill", QStringList() << "/IM" << "chrome.exe" << "/F");
It only works on windows system and closes all browser windows but that is the only solution I have reached and will use for now.

Application name is displayed with its extension when QSystemTrayIcon's showMessage is used in Windows 10

I'm using QSystemTrayIcon to display notification in Windows 10.
Along with the notification, the application name is also displayed.
The problem here is the app name is displayed along with the extension(.exe).
How can the extension(.exe) be removed from the notification?
Try adding this line to your .pro file:
QMAKE_TARGET_DESCRIPTION = "Whatever"
It should change the process name (both in the notifications and in the task manager) to "Whatever".
More variables like this can be found here: Qmake Variables Documentation
Note from the documentation:
This is only utilized if the VERSION or RC_ICONS variable is set and the RC_FILE and RES_FILE variables are not set.
Step-by-step instructions for creating a test application
Create Qt Widgets Application project, containing a QWidget based widget
Create images directory in the project folder, put an icon file into it (for this example let it be icon.ico)
Add a resource file to the project
To that resource file add prefix /, then "Add Files", selecting ./images/icon.ico
In main.cpp change the code to following:
#include "widget.h"
#include <QApplication>
#include <QIcon>
int main(int argc, char *argv[])
{
QCoreApplication::setApplicationName(APP_NAME);
QApplication a(argc, argv);
a.setWindowIcon(QIcon(":/images/icon.ico"));
Widget w;
w.setWindowTitle(qApp->applicationName());
w.setWindowIcon(qApp->windowIcon());
w.show();
return a.exec();
}
In widget.cpp change code to following:
#include "widget.h"
#include "ui_widget.h"
#include <QSystemTrayIcon>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
QSystemTrayIcon *trayIcon = new QSystemTrayIcon(qApp->windowIcon(), this);
trayIcon->show();
connect(trayIcon, &QSystemTrayIcon::activated, [=]() {
trayIcon->showMessage("Title", "Message");
});
}
Widget::~Widget()
{
delete ui;
}
To the bottom of the project (.pro) file add following:
DEFINES += APP_NAME=\\\"AppName\\\"
QMAKE_TARGET_DESCRIPTION = "Whatever"
win32:RC_ICONS += images/icon.ico
Save, run qmake (Build -> Run qmake), rebuild project
Start the application. Now the window title should be "AppName", which came from APP_NAME define, both window and tray icon - icon.ico, and the process name in task manager and notifications - "Whatever". You can make the app display a notification by clicking on the tray icon. Notification should look like this:

QDesktopServices::openUrl does not work, neither for URLs nor for local files, on two platforms

I have a code as simple as this:
int main() {
QUrl url("http://google.com");
if (!QDesktopServices::openUrl(url) )
qDebug() << "Failed to open url";
return 0;
}
Running the code gives "Failed to open url". Tried on Ubuntu with Qt 5.5.1 and on MS Windows with Qt 5.7. No difference.
Local files also do not open:
int main() {
QString file = "/home/user/testfile.pdf";
if (!QDesktopServices::openUrl( QUrl::fromLocalFile(file) ) )
qDebug() << "Failed to open file";
return 0;
}
Again, "Failed to open file". On both Ubuntu and Windows. I can see some discussion in stackoverflow about openUrl, but they are concerned with specific features, such as failing to open urls with spaces, etc. But here it just doesn't work at all, on two independent platforms. What do I miss?
QDesktopServices is part of the Qt GUI module. Therefore, in order to use any function related to QDesktopServices, you will need to instantiate at least a QGuiApplication :
Since the QGuiApplication object does so much initialization, it must
be created before any other objects related to the user interface are
created.
In fact, you can create a QApplication (as #Alex Spataru suggested), since it inherits QGuiApplication. To make your code work, you just need this :
int main(int argc, char *argv[]) {
QApplication app(argc, argv); // just this line
QUrl url("http://google.com");
if ( !QDesktopServices::openUrl(url) )
qDebug() << "Failed to open url";
return 0;
}

Qt, QCoreApplication and QFtp

I want to use QFtp for the first time and googled a lot to find out how it should be used. This, among others is a typical example:
#include <QCoreApplication>
#include <QFtp>
#include <QFile>
int main(int argc, char ** argv)
{
QCoreApplication app(argc, argv);
QFile *file = new QFile( "C:\\Devel\\THP\\tmp\\test.txt" );
file->open(QIODevice::ReadWrite);
QFtp *ftp = new QFtp();
ftp->setTransferMode(QFtp::Active);
ftp->connectToHost("ftp.trolltech.com");
ftp->login();
ftp->cd("qt");
ftp->get("INSTALL",file);
ftp->close();
QObject::connect(ftp, SIGNAL(done(bool)), &app, SLOT(quit()));
int ret = app.exec();
delete ftp;
delete file;
return ret;
}
The question:
As far as I understood, the QCoreApplication app is needed to handle the "done" signal, emmited upon finalization of ftp-get. Now, the ftp->get is called before the connect and even before the app handler is running at all (app.exec() is called afterwards).
What happens, if the file transfer has completed already before the "connect" statement? In fact, that will not happen, but I could put an artificial delay of, say 1 minute between ftp->close() and the connect(...). During this time, the ftp get will surely be finished. What would happen?
Note that QFtp is really only meant for legacy Qt applications and it is now suggested that QNetworkAccessManager and QNetworkReply are used instead, as detailed in the Qt documentation.
That being said, with your connect call being positioned after the connection to the FTP site and retrieving of the file, should the file be downloaded first, the 'quit' signal would never be reached. If you make the connection straight after creating the QFtp object, then this won't be an issue: -
QFtp *ftp = new QFtp();
QObject::connect(ftp, SIGNAL(done(bool)), &app, SLOT(quit()));
This guarantees that the 'quit' slot will be called when the QFtp object emits the 'done' signal.
QFtp *ftp = new QFtp();
QObject::connect(ftp, SIGNAL(done(bool)), &app, SLOT(quit()));
ftp->setTransferMode(QFtp::Active);
ftp->connectToHost("ftp.trolltech.com");
ftp->login();
ftp->cd("qt");
ftp->get("INSTALL",file);
ftp->close();
int ret = app.exec();
In reality though, I would expect the connect in your example would complete before the machine had time to negotiate a connection to another server, login and start the download of the file.

How to load qml file from resources, using QtQuick 2 Controls

I have created Qt Quick 2 Controls project, added resource, placed my qml-file inside resource and added alias to this file. Now I'm wondering, why does next code can't load qml-file as main qml-file:
#include <QDebug>
#include <QFile>
#include <QByteArray>
#include "qtquick2controlsapplicationviewer.h"
int main(int argc, char *argv[]) {
Application app(argc, argv);
QString fileInResource(":main/mainQml");
QFile f(fileInResource);
if (!f.exists()) {
qDebug() << "No file";
} else {
f.open(QIODevice::ReadOnly);
qDebug() << f.readAll();
}
QtQuick2ControlsApplicationViewer viewer;
viewer.setMainQmlFile(fileInResource);
viewer.show();
return app.exec();
}
Since in case of QFile usage, it reads file correct and output whole file, but viewer said:
file:///path/:main/mainQml:-1 File not found
QQmlComponent: Component is not ready
Error: Your root item has to be a Window.`
How to make viewer load my qml-file?
UPD: Added minimal working example -- download it here
The problem is in
void QtQuick2ApplicationViewer::setMainQmlFile(const QString &file)
It uses
setSource(QUrl::fromLocalFile(d->mainQmlFile));
for setting source, and QUrl::fromLocalFile messes up the path. Just change it to
setSource(QUrl(d->mainQmlFile));
and everything works.
UPD:
In your example it's actually component.loadUrl(QUrl::fromLocalFile(d->mainQmlFile));, line 80.
No file file:///path/qrc:/main/mainQml <-
try change the code like below and make sure main.qml file exists in resource .qrc file
QQmlApplicationEngine engine;
engine.rootContext()->setContextProperty("utils", &qmlUtils);
engine.load(QUrl(QStringLiteral("qrc:///main.qml")));
or like this if you are not using the QQmlApplicationEngine
Application app(argc, argv);
QString fileInResource("qrc:///main.qml");

Resources