Hey.
I want to share a simple way to optimize my work time when developing QML applications for Android / iOS / Embedded.
Perhaps, what I have said to someone will seem a battle, but so far I have never read about such an elementary method.
')
The essence of the problem - when developing, debugging or prototyping any mobile application in any language, we usually always go through the same steps: code editing, deployment, launch. And so on to infinity. In the case of mobile development, the code deployment stage can take an impressive amount of time - from 2 to 10 minutes, during which there is nothing to do. Perhaps for some it’s good, but definitely not for those who value their time. In general, I think that this state of affairs is not only me;)
The situation is aggravated for native development tools, for example, under Android, where we always, without options, need to recompile the Java code before the next run on the device.
Qt at first glance has the same problem - each new project build will also be deployed to the device for a long time. But there is only one peculiarity - after all, we can write applications not in Qt / C ++, but in pure QML. In this case, if we do not change the logic in the C ++ part of the application, we do not need to compile anything for the target platform. So, it would be cool to just update the set of qml files of the application and restart the application on the device. After all, saving time on 10 launches would be at least an hour!
Well, since there is a potential opportunity - it is a sin not to use it. Read under the cut that I got.
Having started to dig information on the topic, I first stumbled upon the once-promising QML Live Preview project (
article on Habré ), which allowed developers to start debugging mode in Qt Creator, change the code on the fly and see their edits on the device. It was magic and what I needed, only this Qt Creator module was excluded from the common code base (
link to commit ). Maybe Digia is troubled and transferred it to the commercial version, or maybe it was unstable. I do not know. The main thing is that it is no more.
In general, I had to look for a workaround. It is found in the Qt documentation
page , which discusses a topic such as network transparency when loading resources. The idea is that Qt and QML applications are not there, from where to download QML files and resources such as fonts, images and other things. The source can be a local disk, Qt (qrc) resources, smb-ball or http-server.
The idea of ​​implementation appeared instantly! We deploy an HTTP server on the local machine, the root directory of which will be our project, change the script for loading resources in C ++ parts of the application, check the performance on the desktop, collect it under the mobile phone, check the performance on the mobile phone, rejoice!
Full description of the algorithm:
1) Make sure that our PC and device are on the same local network.
2) We bring the project to the requirements of Qt Network Transparent and a specific pattern:
- all resources in the / assets directory;
- all qml files in the / qml directory;
- within the qml directory, the directory file structure should be a maximum of two levels;
- all inclusions of the type of import “dir” are reduced to the type of import “dir” as Dir;
- all references to components in the subdirectories are reduced from the type MyComp {...} to the form Dir.MyComp {...};
3) Download, configure and run nginx. In the default settings, you need to change only two parameters - the port and the root directory. Then run nginx. Example:
server { listen 8085; ... location / { root D:/Dropbox/work/anyway;
4) In the main.cpp file in the place where qml files are loaded, we change the logic to the following:
bool qmlDebug = true; QString url = "http://192.168.1.22:8085/"; QString qmlLoadPrefix; QString assetsLoadPrefix; QNetworkAccessManager NAManager; QUrl qurl (url+"qml/main.qml"); QNetworkRequest request(qurl); QNetworkReply *reply = NAManager.get(request); QEventLoop eventLoop; QObject::connect(reply, SIGNAL(finished()), &eventLoop, SLOT(quit())); eventLoop.exec(); if (reply->error() != QNetworkReply::NoError) { qmlDebug = false; qDebug() << "Error loading qml by network. Load from resources!"; } if (qmlDebug) { qmlLoadPrefix = url+"qml/"; assetsLoadPrefix = url+"assets/"; } else { qmlLoadPrefix = "qrc:/"; assetsLoadPrefix = "qrc:/"; } engine.rootContext()->setContextProperty("qmlLoadPrefix", qmlLoadPrefix); engine.rootContext()->setContextProperty("assetsLoadPrefix", assetsLoadPrefix); engine.load(QUrl(qmlLoadPrefix+"main.qml"));
Here we set the URL of our PC in the local network, as well as two variables qmlLoadPrefix and assetsLoadPrefix. As it is not difficult to guess, these are just prefixes for accessing the resources and qml-files of the application, depending on the current configuration of the application. So during the active development phase, we will be able to quickly download the required resources via http, and when releasing the application, download everything from the resource files of the application itself.
5) Well, the last step - we change all occurrences of the type “qrc: //myImg.png” on assetsLoadPrefix + “myImg.png” in all qml files of the project.
That's all. It remains to note that now you need to launch the application for debugging not using the large green “Play” button on the left Qt Creator toolbar, but using the small “Play” button on the bottom toolbar in the “Application Output” section. True, this button will be unavailable immediately after launching Qt Creator and you will need to start the application for the first time in the old fashioned way, but then you only need to use it. At the same time, all the necessary debug messages will be added to the Qt Creator log, and if you need full debugging, it will also work in the normal mode.
Of course, this is not so hot a hack and it still will not save from rebuilding the application when writing C ++ code, but even in this form we get much more convenience when developing applications for any of the platforms.
I suggest in the comments to share my thoughts and suggestions on how to further optimize the development of Qt-applications and their advantages over native applications for iOS and Android.